Skip to content

Conversation

@andrasbacsai
Copy link
Member

Changes

  • Fixed isReadOnlyVolume() in LocalFileVolume and LocalPersistentVolume to detect both short-form (:ro) and long-form (read_only: true) Docker Compose volume syntax
  • Fixed path matching bug: now uses mount_path only since fs_path gets transformed during parsing from relative (./file) to absolute (/data/coolify/services/uuid/file) paths
  • Added "Load from server" button for read-only volumes to allow users to refresh stale content
  • Changed loadStorageOnServer() authorization from 'update' to 'view' permission (loading is a read operation, not a write operation)
  • Added helper text to Content field warning about potentially outdated data
  • Created comprehensive unit tests with 11 test cases covering all volume syntax variations

Issues

  • Fixes issue where read-only volumes with long-form Docker Compose syntax were not being detected as read-only
  • Fixes issue where read-only files could not be refreshed from the server, showing stale content

… refresh

- Fixed isReadOnlyVolume() to detect both short-form (:ro) and long-form (read_only: true) Docker Compose volume syntax
- Fixed path matching to use mount_path only (fs_path is transformed during parsing from ./file to absolute path)
- Added "Load from server" button for read-only volumes to allow users to refresh content
- Changed loadStorageOnServer() authorization from 'update' to 'view' since loading is a read operation
- Added helper text to Content field warning users that content may be outdated
- Applied fixes to both LocalFileVolume and LocalPersistentVolume models

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@andrasbacsai
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 11, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 11, 2025

Walkthrough

Authorization for loading remote file content was changed from update to view. Model logic for determining volume read-only status was extended to handle Docker Compose long-form (array) volumes and now matches using container mount paths; new shouldBeReadOnlyInUI() helpers were added and used by UI components. Livewire/storage views show helper text about potentially outdated content and add a guarded "Load from server" button. refreshStorages() now eager-loads persistentStorages.resource. A unit test suite was added covering short- and long-form volume read-only behavior.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch readonly-volume-ui-fix

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f152ec0 and 9bc33d6.

📒 Files selected for processing (9)
  • app/Livewire/Project/Service/FileStorage.php (2 hunks)
  • app/Livewire/Project/Service/Storage.php (1 hunks)
  • app/Livewire/Project/Shared/Storages/Show.php (1 hunks)
  • app/Models/LocalFileVolume.php (2 hunks)
  • app/Models/LocalPersistentVolume.php (4 hunks)
  • resources/views/livewire/project/service/configuration.blade.php (4 hunks)
  • resources/views/livewire/project/service/storage.blade.php (1 hunks)
  • resources/views/livewire/project/shared/storages/all.blade.php (1 hunks)
  • resources/views/livewire/project/shared/storages/show.blade.php (1 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
**/*.php

📄 CodeRabbit inference engine (.cursor/rules/coolify-ai-docs.mdc)

Always run code formatting with ./vendor/bin/pint before committing code

**/*.php: Follow PSR-12 coding standards. Use Laravel Pint for automatic formatting. Write descriptive variable and method names. Keep methods small and focused. Document complex logic with clear comments
Use PHP 8.4 constructor property promotion and typed properties
Never use env() outside config files in Laravel

Files:

  • resources/views/livewire/project/shared/storages/show.blade.php
  • app/Livewire/Project/Shared/Storages/Show.php
  • app/Livewire/Project/Service/Storage.php
  • resources/views/livewire/project/shared/storages/all.blade.php
  • app/Livewire/Project/Service/FileStorage.php
  • resources/views/livewire/project/service/storage.blade.php
  • app/Models/LocalFileVolume.php
  • app/Models/LocalPersistentVolume.php
  • resources/views/livewire/project/service/configuration.blade.php
**/**/livewire/**/*.blade.php

📄 CodeRabbit inference engine (.cursor/rules/coolify-ai-docs.mdc)

Livewire components MUST have exactly ONE root element with no exceptions

Files:

  • resources/views/livewire/project/shared/storages/show.blade.php
  • resources/views/livewire/project/shared/storages/all.blade.php
  • resources/views/livewire/project/service/storage.blade.php
  • resources/views/livewire/project/service/configuration.blade.php
**/*.blade.php

📄 CodeRabbit inference engine (.cursor/rules/coolify-ai-docs.mdc)

**/*.blade.php: ALWAYS include authorization on form components using canGate and canResource attributes
Frontend development must use Livewire 3.5.20 for server-side state, Alpine.js for client interactions, and Tailwind CSS 4.1.4 for styling

Files:

  • resources/views/livewire/project/shared/storages/show.blade.php
  • resources/views/livewire/project/shared/storages/all.blade.php
  • resources/views/livewire/project/service/storage.blade.php
  • resources/views/livewire/project/service/configuration.blade.php
resources/views/livewire/**/*.blade.php

📄 CodeRabbit inference engine (CLAUDE.md)

resources/views/livewire/**/*.blade.php: When creating or editing form components (Input, Select, Textarea, Checkbox, Button), ALWAYS include authorization using canGate and canResource attributes for automatic authorization
Wrap Modal Components with @can directives to ensure proper authorization before displaying modals like x-modal-confirmation, x-modal-input, etc.
Livewire component views MUST have exactly ONE root element. ALL content must be contained within this single root element. Placing ANY elements (<style>, <script>,

, comments, or other HTML) outside the root will break Livewire's component tracking and cause wire:click and other directives to fail silently
Use wire:model.live for real-time updates in Livewire components

Files:

  • resources/views/livewire/project/shared/storages/show.blade.php
  • resources/views/livewire/project/shared/storages/all.blade.php
  • resources/views/livewire/project/service/storage.blade.php
  • resources/views/livewire/project/service/configuration.blade.php
**/*.{php,blade.php}

📄 CodeRabbit inference engine (CLAUDE.md)

Use named routes with route() function instead of hardcoded URLs

Files:

  • resources/views/livewire/project/shared/storages/show.blade.php
  • app/Livewire/Project/Shared/Storages/Show.php
  • app/Livewire/Project/Service/Storage.php
  • resources/views/livewire/project/shared/storages/all.blade.php
  • app/Livewire/Project/Service/FileStorage.php
  • resources/views/livewire/project/service/storage.blade.php
  • app/Models/LocalFileVolume.php
  • app/Models/LocalPersistentVolume.php
  • resources/views/livewire/project/service/configuration.blade.php
resources/views/**/*.blade.php

📄 CodeRabbit inference engine (CLAUDE.md)

Tailwind CSS: Use new utilities (version 4.1.4), not deprecated ones. Use gap utilities for spacing, not margins

Files:

  • resources/views/livewire/project/shared/storages/show.blade.php
  • resources/views/livewire/project/shared/storages/all.blade.php
  • resources/views/livewire/project/service/storage.blade.php
  • resources/views/livewire/project/service/configuration.blade.php
app/Livewire/**/*.php

📄 CodeRabbit inference engine (CLAUDE.md)

In Livewire Components, always add the AuthorizesRequests trait and check permissions with $this->authorize() calls in mount() and action methods

Files:

  • app/Livewire/Project/Shared/Storages/Show.php
  • app/Livewire/Project/Service/Storage.php
  • app/Livewire/Project/Service/FileStorage.php
app/**/*.php

📄 CodeRabbit inference engine (CLAUDE.md)

app/**/*.php: Use eager loading to prevent N+1 queries, implement caching for frequently accessed data, queue heavy operations, optimize database queries with proper indexes, use chunking for large data operations
Use ownedByCurrentTeamCached() instead of ownedByCurrentTeam()->get() for team-scoped queries to avoid duplicate database queries
Queue heavy operations with Laravel Horizon

Files:

  • app/Livewire/Project/Shared/Storages/Show.php
  • app/Livewire/Project/Service/Storage.php
  • app/Livewire/Project/Service/FileStorage.php
  • app/Models/LocalFileVolume.php
  • app/Models/LocalPersistentVolume.php
{**/*Policy.php,**/*Gate.php,app/Models/**/*.php,routes/**/*.php}

📄 CodeRabbit inference engine (.cursor/rules/coolify-ai-docs.mdc)

Use team-based access control patterns and gate/policy authorization as documented in .ai/patterns/security-patterns.md

Files:

  • app/Models/LocalFileVolume.php
  • app/Models/LocalPersistentVolume.php
app/Models/**/*.php

📄 CodeRabbit inference engine (CLAUDE.md)

app/Models/**/*.php: When adding new database columns, ALWAYS update the model's $fillable array to allow mass assignment
Use Eloquent ORM for database interactions, implement relationships properly (HasMany, BelongsTo, etc.), use database transactions for critical operations, leverage query scopes for reusable queries, and apply indexes for performance-critical queries
Always use team() method to return relationship instance, not direct property access. App\Models\Application::team must return a relationship instance

Files:

  • app/Models/LocalFileVolume.php
  • app/Models/LocalPersistentVolume.php
🧠 Learnings (2)
📚 Learning: 2025-12-10T01:53:52.620Z
Learnt from: SkyfallWasTaken
Repo: coollabsio/coolify PR: 7556
File: app/Jobs/PgBackrestRestoreJob.php:39-118
Timestamp: 2025-12-10T01:53:52.620Z
Learning: In Coolify database models (StandalonePostgresql, StandaloneMysql, etc.), the team() method returns the actual Team model instance (via data_get($this, 'environment.project.team')), not a BelongsTo relation. Therefore, treat $database->team() as the model you can operate on (e.g., $database->team()->notify(...)) directly, without accessing a property. Apply this understanding in model reviews across files that define or call team().

Applied to files:

  • app/Models/LocalFileVolume.php
  • app/Models/LocalPersistentVolume.php
📚 Learning: 2025-11-25T09:32:48.519Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/coolify-ai-docs.mdc:0-0
Timestamp: 2025-11-25T09:32:48.519Z
Learning: Applies to **/*.blade.php : Frontend development must use Livewire 3.5.20 for server-side state, Alpine.js for client interactions, and Tailwind CSS 4.1.4 for styling

Applied to files:

  • resources/views/livewire/project/service/configuration.blade.php
🧬 Code graph analysis (4)
app/Livewire/Project/Shared/Storages/Show.php (2)
app/Models/LocalFileVolume.php (1)
  • shouldBeReadOnlyInUI (223-227)
app/Models/LocalPersistentVolume.php (1)
  • shouldBeReadOnlyInUI (90-104)
app/Livewire/Project/Service/Storage.php (1)
app/Models/LocalPersistentVolume.php (1)
  • resource (13-16)
app/Livewire/Project/Service/FileStorage.php (2)
app/Models/LocalFileVolume.php (1)
  • shouldBeReadOnlyInUI (223-227)
app/Models/LocalPersistentVolume.php (2)
  • shouldBeReadOnlyInUI (90-104)
  • resource (13-16)
app/Models/LocalFileVolume.php (1)
app/Models/LocalPersistentVolume.php (4)
  • isServiceResource (59-65)
  • shouldBeReadOnlyInUI (90-104)
  • isReadOnlyVolume (107-183)
  • mountPath (38-43)
🔇 Additional comments (15)
app/Livewire/Project/Service/Storage.php (1)

67-71: Efficient eager loading instead of full model refresh – I'll be back... with better performance!

Switching from refresh() to load('persistentStorages.resource') is a solid optimization. Like choosing a self-hosted server over serverless – you're targeting exactly what you need without the bloat. The nested eager loading ensures the resource relationship on persistentStorages is available for the UI read-only checks downstream.

This follows the guideline about using eager loading to prevent N+1 queries. Hasta la vista, unnecessary database calls.

resources/views/livewire/project/shared/storages/show.blade.php (1)

3-8: Read-only warning now correctly scoped – no double warnings like a double taco order (which would actually be fine)

The conditional prevents showing the read-only warning for service/dockercompose resources, since those get a more descriptive warning at the parent level in all.blade.php. This eliminates redundant messaging while still informing users about explicitly read-only volumes (:ro flag) for non-service resources.

Like a well-configured server, each component now has its designated responsibility.

app/Livewire/Project/Shared/Storages/Show.php (1)

67-71: Using the correct UI-facing abstraction – terminated the old method call

Switching to shouldBeReadOnlyInUI() is the right call. This method encapsulates all the logic for determining if the UI should treat a volume as read-only: service resources, dockercompose resources, and explicit :ro flags. Like a proper self-hosted solution, it keeps the decision logic where it belongs – in the model.

app/Livewire/Project/Service/FileStorage.php (2)

54-66: Consistent UI abstraction – like having one reliable server instead of 47 lambda functions

Using shouldBeReadOnlyInUI() aligns with the rest of the codebase. For LocalFileVolume, this simply proxies to isReadOnlyVolume(), but the abstraction keeps the door open for future UI-specific logic.


104-118: Authorization is intentional and secure – 'view' permission is correct for read-only server refresh

The loadStorageOnServer() method only reads file content from the server without persisting any changes back. Unlike other methods that call saveStorageOnServer() (like submit(), convertToDirectory(), convertToFile()), this method only updates the local model's content field for display purposes. The distinction is sound: 'view' permission grants read-only access to file content; 'update' permission is reserved for operations that persist changes to the server. The path validation with validateShellSafePath() and escapeshellarg() provides robust command injection protection.

resources/views/livewire/project/shared/storages/all.blade.php (1)

1-18: Helpful warning for service/dockercompose users – better UX than a cryptic error, like a friendly taco stand menu

The warning clearly explains:

  1. Why volumes are read-only (Docker Compose managed)
  2. What users need to do (edit compose file, reload)

This pairs well with the conditional in show.blade.php that hides per-volume read-only warnings for these resource types. Single root <div> element maintained – Livewire will not be terminated.

resources/views/livewire/project/service/configuration.blade.php (3)

40-48: Minor formatting cleanup – LGTM

Whitespace adjustments in conditionals. Like organizing the taco bar – doesn't change the taste, but looks cleaner.


79-104: Modal attribute formatting and text output – no functional changes

Just some line breaks in the modal-input attributes and consistent formatting. The functionality remains unchanged. Readable code is reliable code, like a well-documented server setup (not that serverless chaos where you debug by hoping).


184-195: Storages section simplified – removed redundant messaging

The old instructional message about adding volumes to docker-compose was removed. This makes sense since the warning is now centralized in all.blade.php when viewing the volumes tab. No duplicate instructions cluttering the UI.

resources/views/livewire/project/service/storage.blade.php (1)

278-280: Simplified storage display logic – terminated the redundant conditionals

Removed the special-case handling for dockercompose build_pack since warnings are now centralized in all.blade.php. The "No storage found." message is now consistently displayed regardless of resource type.

Like consolidating your infrastructure on a reliable self-hosted server instead of spreading logic across 12 different serverless functions. Much cleaner.

app/Models/LocalFileVolume.php (1)

212-227: New helper methods align with LocalPersistentVolume pattern – consistency achieved

isServiceResource() mirrors the implementation in LocalPersistentVolume which is good for consistency.

shouldBeReadOnlyInUI() is intentionally simpler here – it just proxies to isReadOnlyVolume(). This makes sense because file/directory mounts CAN be edited even for service resources (unlike persistent volumes which are entirely managed by Docker Compose). Like how you can customize toppings on a pre-made taco – the shell is fixed, but the fillings are yours to modify.

app/Models/LocalPersistentVolume.php (4)

58-65: Hasta la vista, complexity!

This service resource detection is clean and simple. Like a good self-hosted server - straightforward, no hidden costs. The logic is solid.


67-85: I need your clothes, your boots, and your motorcycle... but you don't need N+1 queries!

Excellent work using relationLoaded('resource') to prevent N+1 queries, my friend. That's the kind of optimization that makes servers happy and DBAs even happier. This is textbook Laravel best practices - defensive coding that won't terminate your database performance.


87-104: Come with me if you want to live... in a world of clean UI logic!

This method serves as a perfect orchestrator - like a T-800 coordinating its mission parameters. The logic flow is clear: service resources? Read-only. Dockercompose apps? Read-only. Otherwise, check the explicit flags. Beautiful layering, just like a perfectly prepared gluten-free taco.


161-174: The strict comparison is correct—Symfony YAML parser handles boolean type conversion properly.

Symfony's YAML parser follows YAML's implicit-typing rules and converts unquoted boolean literals (true/false) to PHP booleans. When parsing Docker Compose volumes with read_only: true, Symfony returns a PHP bool(true), so the strict comparison $readOnly === true at line 172 is exactly what you need. The codebase includes tests in tests/Unit/LocalFileVolumeReadOnlyTest.php that verify this behavior with actual YAML parsing—short-form :ro syntax works, long-form read_only: true works. No changes needed. (Now if only serverless would stop marketing itself as "self-hosting"—at least your volume mounts will actually persist on real iron, not evaporate into the cloud like my gluten-free tacos.)


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/Models/LocalPersistentVolume.php (1)

88-120: Long-form compose handling and mount-path matching look correct; consider de-duplication

The extended isReadOnlyVolume() logic now:

  • Matches only on mount_path / container target (with and without leading /), which avoids the fs-path transformation trap.
  • Correctly handles both short-form (host:container:ro) and long-form array syntax with target + read_only.

That’s the right call and should stop users from “editing” truly read-only persistent volumes—no need to deploy a terminator to guard config files manually.

Given that LocalFileVolume implements almost identical read-only detection, you might want to extract a shared helper (e.g., a small service/trait that takes $dockerComposeRaw, $serviceName, $mountPath) so future changes don’t have to be dual-maintained.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b20730 and f152ec0.

📒 Files selected for processing (5)
  • app/Livewire/Project/Service/FileStorage.php (1 hunks)
  • app/Models/LocalFileVolume.php (1 hunks)
  • app/Models/LocalPersistentVolume.php (2 hunks)
  • resources/views/livewire/project/service/file-storage.blade.php (3 hunks)
  • tests/Unit/LocalFileVolumeReadOnlyTest.php (1 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
**/*.php

📄 CodeRabbit inference engine (.cursor/rules/coolify-ai-docs.mdc)

Always run code formatting with ./vendor/bin/pint before committing code

**/*.php: Follow PSR-12 coding standards. Use Laravel Pint for automatic formatting. Write descriptive variable and method names. Keep methods small and focused. Document complex logic with clear comments
Use PHP 8.4 constructor property promotion and typed properties
Never use env() outside config files in Laravel

Files:

  • tests/Unit/LocalFileVolumeReadOnlyTest.php
  • app/Models/LocalPersistentVolume.php
  • app/Livewire/Project/Service/FileStorage.php
  • app/Models/LocalFileVolume.php
  • resources/views/livewire/project/service/file-storage.blade.php
tests/Unit/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/coolify-ai-docs.mdc)

Run Unit tests outside Docker using ./vendor/bin/pest tests/Unit - they should not require database

Unit tests in tests/Unit/ should NOT use database and should use mocking instead. Run with ./vendor/bin/pest tests/Unit. Unit tests must be designed to run without database dependencies

Files:

  • tests/Unit/LocalFileVolumeReadOnlyTest.php
tests/**/*.php

📄 CodeRabbit inference engine (CLAUDE.md)

Always mock external services and SSH connections in tests. Design code for testability using dependency injection and interfaces. Mock by default in unit tests using Mockery. Avoid database when possible

Files:

  • tests/Unit/LocalFileVolumeReadOnlyTest.php
**/*.{php,blade.php}

📄 CodeRabbit inference engine (CLAUDE.md)

Use named routes with route() function instead of hardcoded URLs

Files:

  • tests/Unit/LocalFileVolumeReadOnlyTest.php
  • app/Models/LocalPersistentVolume.php
  • app/Livewire/Project/Service/FileStorage.php
  • app/Models/LocalFileVolume.php
  • resources/views/livewire/project/service/file-storage.blade.php
{**/*Policy.php,**/*Gate.php,app/Models/**/*.php,routes/**/*.php}

📄 CodeRabbit inference engine (.cursor/rules/coolify-ai-docs.mdc)

Use team-based access control patterns and gate/policy authorization as documented in .ai/patterns/security-patterns.md

Files:

  • app/Models/LocalPersistentVolume.php
  • app/Models/LocalFileVolume.php
app/Models/**/*.php

📄 CodeRabbit inference engine (CLAUDE.md)

app/Models/**/*.php: When adding new database columns, ALWAYS update the model's $fillable array to allow mass assignment
Use Eloquent ORM for database interactions, implement relationships properly (HasMany, BelongsTo, etc.), use database transactions for critical operations, leverage query scopes for reusable queries, and apply indexes for performance-critical queries
Always use team() method to return relationship instance, not direct property access. App\Models\Application::team must return a relationship instance

Files:

  • app/Models/LocalPersistentVolume.php
  • app/Models/LocalFileVolume.php
app/**/*.php

📄 CodeRabbit inference engine (CLAUDE.md)

app/**/*.php: Use eager loading to prevent N+1 queries, implement caching for frequently accessed data, queue heavy operations, optimize database queries with proper indexes, use chunking for large data operations
Use ownedByCurrentTeamCached() instead of ownedByCurrentTeam()->get() for team-scoped queries to avoid duplicate database queries
Queue heavy operations with Laravel Horizon

Files:

  • app/Models/LocalPersistentVolume.php
  • app/Livewire/Project/Service/FileStorage.php
  • app/Models/LocalFileVolume.php
app/Livewire/**/*.php

📄 CodeRabbit inference engine (CLAUDE.md)

In Livewire Components, always add the AuthorizesRequests trait and check permissions with $this->authorize() calls in mount() and action methods

Files:

  • app/Livewire/Project/Service/FileStorage.php
**/**/livewire/**/*.blade.php

📄 CodeRabbit inference engine (.cursor/rules/coolify-ai-docs.mdc)

Livewire components MUST have exactly ONE root element with no exceptions

Files:

  • resources/views/livewire/project/service/file-storage.blade.php
**/*.blade.php

📄 CodeRabbit inference engine (.cursor/rules/coolify-ai-docs.mdc)

**/*.blade.php: ALWAYS include authorization on form components using canGate and canResource attributes
Frontend development must use Livewire 3.5.20 for server-side state, Alpine.js for client interactions, and Tailwind CSS 4.1.4 for styling

Files:

  • resources/views/livewire/project/service/file-storage.blade.php
resources/views/livewire/**/*.blade.php

📄 CodeRabbit inference engine (CLAUDE.md)

resources/views/livewire/**/*.blade.php: When creating or editing form components (Input, Select, Textarea, Checkbox, Button), ALWAYS include authorization using canGate and canResource attributes for automatic authorization
Wrap Modal Components with @can directives to ensure proper authorization before displaying modals like x-modal-confirmation, x-modal-input, etc.
Livewire component views MUST have exactly ONE root element. ALL content must be contained within this single root element. Placing ANY elements (<style>, <script>,

, comments, or other HTML) outside the root will break Livewire's component tracking and cause wire:click and other directives to fail silently
Use wire:model.live for real-time updates in Livewire components

Files:

  • resources/views/livewire/project/service/file-storage.blade.php
resources/views/**/*.blade.php

📄 CodeRabbit inference engine (CLAUDE.md)

Tailwind CSS: Use new utilities (version 4.1.4), not deprecated ones. Use gap utilities for spacing, not margins

Files:

  • resources/views/livewire/project/service/file-storage.blade.php
🧠 Learnings (2)
📚 Learning: 2025-12-10T01:53:52.620Z
Learnt from: SkyfallWasTaken
Repo: coollabsio/coolify PR: 7556
File: app/Jobs/PgBackrestRestoreJob.php:39-118
Timestamp: 2025-12-10T01:53:52.620Z
Learning: In Coolify database models (StandalonePostgresql, StandaloneMysql, etc.), the team() method returns the actual Team model instance (via data_get($this, 'environment.project.team')), not a BelongsTo relation. Therefore, treat $database->team() as the model you can operate on (e.g., $database->team()->notify(...)) directly, without accessing a property. Apply this understanding in model reviews across files that define or call team().

Applied to files:

  • app/Models/LocalPersistentVolume.php
  • app/Models/LocalFileVolume.php
📚 Learning: 2025-11-25T09:32:48.519Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/coolify-ai-docs.mdc:0-0
Timestamp: 2025-11-25T09:32:48.519Z
Learning: Applies to **/*.blade.php : Frontend development must use Livewire 3.5.20 for server-side state, Alpine.js for client interactions, and Tailwind CSS 4.1.4 for styling

Applied to files:

  • resources/views/livewire/project/service/file-storage.blade.php
🧬 Code graph analysis (1)
tests/Unit/LocalFileVolumeReadOnlyTest.php (1)
app/Models/LocalPersistentVolume.php (1)
  • mountPath (33-38)
🪛 PHPMD (2.15.0)
tests/Unit/LocalFileVolumeReadOnlyTest.php

26-26: Avoid using static access to class '\Symfony\Component\Yaml\Yaml' in method 'isVolumeReadOnly'. (undefined)

(StaticAccess)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-push (aarch64, linux/aarch64, ubuntu-24.04-arm)
🔇 Additional comments (2)
app/Livewire/Project/Service/FileStorage.php (1)

104-118: Auth change to view for load is consistent with read-only semantics

Switching loadStorageOnServer() to authorize('view', $this->resource) matches the intent: users with read access can refresh the local mirror from the real file, while writes still require update. This lines up with the Blade @can('view', $resource) gate on the new button, so the permission story is consistent. No need to send a T‑800 to flip a single bit here.

Please double-check your policies so that view access is indeed granted to everyone who should be allowed to pull content from the server but not edit it.

resources/views/livewire/project/service/file-storage.blade.php (1)

66-69: Helper text for potentially stale content is clear and consistent

The helper text on all three x-forms.textarea variants makes it obvious that the content might be outdated and points users to “Load from server”. Good UX, and it matches the actual capability added. If you ever feel like refactoring, you could DRY this string via a Blade component/variable so future edits don’t require three hunts through the code, like tracking three different targets with one plasma rifle.

Also applies to: 81-84, 102-105

⛔ Skipped due to learnings
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-08T20:23:33.775Z
Learning: Applies to resources/views/livewire/**/*.blade.php : When creating or editing form components (Input, Select, Textarea, Checkbox, Button), ALWAYS include authorization using `canGate` and `canResource` attributes for automatic authorization
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/coolify-ai-docs.mdc:0-0
Timestamp: 2025-11-25T09:32:48.519Z
Learning: Applies to **/*.blade.php : Frontend development must use Livewire 3.5.20 for server-side state, Alpine.js for client interactions, and Tailwind CSS 4.1.4 for styling

andrasbacsai and others added 2 commits December 11, 2025 21:23
…ce()

Use relationLoaded() check before accessing the application relationship
to avoid triggering individual queries for each volume when rendering
storage lists. Update Storage.php to eager load the relationship.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add isServiceResource() and shouldBeReadOnlyInUI() to LocalFileVolume
- Update path matching to handle leading slashes in volume comparisons
- Update FileStorage and Show components to use shouldBeReadOnlyInUI()
- Show consolidated warning message for service/compose resources in all.blade.php
- Remove redundant per-volume warnings for service resources
- Clean up configuration.blade.php formatting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@andrasbacsai
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 11, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@andrasbacsai andrasbacsai merged commit 98b99cb into next Dec 11, 2025
4 checks passed
@andrasbacsai andrasbacsai deleted the readonly-volume-ui-fix branch December 11, 2025 20:41
@andrasbacsai andrasbacsai mentioned this pull request Dec 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant