Skip to content

Conversation

@andrasbacsai
Copy link
Member

@andrasbacsai andrasbacsai commented Nov 4, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Improved form data synchronization reliability across project settings and service editors.
  • New Features

    • Confirmation modal added for Nginx configuration generation.
    • Unified form sync behavior for more consistent save/load flows and clearer field updates.
    • More explicit form validations to surface input errors earlier.
  • Tests

    • Added test coverage for application setting boolean casting.
  • Chores

    • Updated product version to 4.0.0-beta.440.

…asts

- Changed `$cast` to `$casts` in ApplicationSetting model to enable proper boolean casting for new fields.
- Added boolean fields: `is_spa`, `is_build_server_enabled`, `is_preserve_repository_enabled`, `is_container_label_escape_enabled`, `is_container_label_readonly_enabled`, and `use_build_secrets`.

fix: Update Livewire component to reflect new property names

- Updated references in the Livewire component for the new camelCase property names.
- Adjusted bindings and IDs for consistency with the updated model.

test: Add unit tests for ApplicationSetting boolean casting

- Created tests to verify boolean casting for `is_static` and other boolean fields in ApplicationSetting.
- Ensured all boolean fields are correctly defined in the casts array.

test: Implement tests for SynchronizesModelData trait

- Added tests to verify the functionality of the SynchronizesModelData trait, ensuring it correctly syncs properties between the component and the model.
- Included tests for handling non-existent properties gracefully.
Enhance Livewire component data synchronization guidelines
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 4, 2025

Walkthrough

This PR removes a shared Livewire synchronization trait, introduces per-component public syncData(bool $toModel = false) methods with camelCase public properties and #[Validate] attributes, adds a PostgreSQL restore Artisan command, fixes ApplicationSetting casts, updates Blade bindings, adds tests, and updates docs and version strings.

Changes

Cohort / File(s) Summary
Trait removal
app/Livewire/Concerns/SynchronizesModelData.php
Removed the SynchronizesModelData trait and its abstract API (getModelBindings, syncToModel, syncFromModel).
Livewire components: syncData + validation + renames
app/Livewire/Project/Application/General.php, app/Livewire/Project/Service/EditDomain.php, app/Livewire/Project/Service/FileStorage.php, app/Livewire/Project/Service/ServiceApplicationView.php, app/Livewire/Project/Shared/HealthChecks.php
Replaced trait usage with public syncData(bool $toModel = false) methods, converted snake_case properties to camelCase, added per-field #[Validate] attributes, and updated mount/submit/instant-save/error flows to use new sync or inline assignments.
Blade template bindings
resources/views/livewire/project/application/general.blade.php
Updated wire:model and related bindings from snake_case → camelCase; adjusted some UI actions/modal flows to match refactored component properties.
Console command (DB restore)
app/Console/Commands/Cloud/RestoreDatabase.php
Added cloud:restore-database {file} {--debug} command for PostgreSQL dumps (gzipped supported), with development-only guard, drop-and-restore logic, proc handling, temp-file management, debug output, and error handling.
Model casting fix
app/Models/ApplicationSetting.php
Fixed protected $castprotected $casts and added boolean casts for additional fields (e.g., is_spa, is_build_server_enabled, use_build_secrets, etc.).
Unit tests
tests/Unit/ApplicationSettingStaticCastTest.php
New tests verifying boolean casting for ApplicationSetting and that expected fields are present in casts().
Docs / frontend patterns
.cursor/rules/frontend-patterns.mdc
Added detailed Livewire Component Data Synchronization Pattern docs (syncData approach, examples, pitfalls, testing checklist).
Version bumps
config/constants.php, other/nightly/versions.json, versions.json
Updated beta version strings.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Blade
    participant Component
    participant Model

    User->>Blade: interact / fill form
    Blade->>Component: wire:model (camelCase)
    Component->>Component: update property (validated via #[Validate])
    User->>Component: submit
    Component->>Component: syncData(toModel: true)
    Component->>Model: map & assign fields
    Model->>Model: save()
    Component->>Blade: update view/state
Loading
sequenceDiagram
    participant Dev
    participant Cmd as RestoreDatabase
    participant FS as DumpFile
    participant DB as PostgreSQL

    Dev->>Cmd: cloud:restore-database file.sql[.gz] --debug
    Cmd->>Cmd: isDevelopment() check
    Cmd->>FS: verify/read (decompress if gz)
    Cmd->>DB: dropAllTables()
    Cmd->>DB: pg_restore / psql restore
    alt success
        Cmd->>Dev: success
    else failure
        Cmd->>Dev: error + non-zero exit
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Focus areas:
    • app/Livewire/Project/Application/General.php — large API rename, many validation attributes, and syncData integration.
    • app/Console/Commands/Cloud/RestoreDatabase.php — process execution, temp-file handling, environment guard, and error paths.
    • Blade bindings in resources/views/livewire/project/application/general.blade.php — ensure all wire:model targets match renamed properties.
    • Consistency and behavior of new syncData(bool $toModel = false) across modified components.

Possibly related PRs

Suggested reviewers

  • peaklabs-dev
  • ShadowArcanist

Poem

🐇 I hopped from snake to camel with care,
syncData hummed and fixed each pair.
Casts now true, a DB revive,
Tests and docs to keep code alive.
Snippets sparkle — refactor flair!

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The title 'v4.0.0-beta.440' is a version bump identifier that does not describe the actual changes made in the changeset. The PR contains significant feature changes including new command implementations, trait removal, synchronization mechanism refactoring, and model property changes. Provide a descriptive title that summarizes the main change, e.g., 'Refactor Livewire model synchronization to use camelCase properties' or 'Replace SynchronizesModelData trait with explicit syncData() method'.
Description check ⚠️ Warning The pull request description is entirely empty. The required template specifies multiple sections including Changes, Issues, and a completion checklist, none of which have been filled out. Complete the PR description by adding a Changes section listing the key modifications, an Issues section with relevant issue/discussion links, and confirming the checklist items have been reviewed.
✨ 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 next

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: 4

🧹 Nitpick comments (3)
.cursor/rules/frontend-patterns.mdc (1)

270-616: Comprehensive documentation for the new syncData() pattern.

The documentation thoroughly covers the new manual synchronization approach, including property naming conventions, validation with #[Validate] attributes, step-by-step implementation guide, special patterns, and common pitfalls. This will help developers adopt the new pattern consistently across the codebase.

Consider adding DON'T examples alongside the DO examples to illustrate anti-patterns developers should avoid. For instance:

// ❌ DON'T: Use snake_case for component properties
public string $git_repository;

// ✅ DO: Use camelCase for component properties
public string $gitRepository;
// ❌ DON'T: Forget to validate before syncing to model
public function syncData(bool $toModel = false): void
{
    if ($toModel) {
        // Missing: $this->validate();
        $this->application->name = $this->name;
        ...
    }
}

As per coding guidelines: "Include both DO and DON'T examples in rules."

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

25-30: Duplicate validation rules detected.

The fqdn property has validation defined in both the #[Validate] attribute (line 25) and the $rules array (lines 28-30). While this doesn't cause errors, it's redundant. Consider removing the $rules array and relying solely on the #[Validate] attribute for consistency with the new pattern documented in frontend-patterns.mdc.

Apply this diff to remove the redundant rules:

 #[Validate(['nullable'])]
 public ?string $fqdn = null;
-
-    protected $rules = [
-        'fqdn' => 'nullable',
-    ];

61-115: Submit flow deviates from documented syncData() pattern.

The submit() method manually assigns fqdn to the model (line 79) and calls validate() + save() separately (lines 94-95), rather than using syncData(toModel: true) which would handle validation and saving together. While this approach works and allows for domain transformation and conflict checking between assignment and save, it's inconsistent with the pattern documented in frontend-patterns.mdc.

Consider refactoring to align with the documented pattern, or document this as an acceptable variation for cases requiring intermediate validation/transformation steps.

Possible refactor:

             $warning = sslipDomainWarning($this->fqdn);
             if ($warning) {
                 $this->dispatch('warning', __('warning.sslipdomain'));
             }
-            // Sync to model for domain conflict check (without validation)
-            $this->application->fqdn = $this->fqdn;
+
             // Check for domain conflicts if not forcing save
             if (! $this->forceSaveDomains) {
+                // Temporarily set fqdn for conflict checking
+                $tempFqdn = $this->application->fqdn;
+                $this->application->fqdn = $this->fqdn;
+
                 $result = checkDomainUsage(resource: $this->application);
                 if ($result['hasConflicts']) {
                     $this->domainConflicts = $result['conflicts'];
                     $this->showDomainConflictModal = true;
-
+                    // Restore original fqdn
+                    $this->application->fqdn = $tempFqdn;
                     return;
                 }
+                // Restore original fqdn before syncing
+                $this->application->fqdn = $tempFqdn;
             } else {
                 // Reset the force flag after using it
                 $this->forceSaveDomains = false;
             }
 
-            $this->validate();
-            $this->application->save();
+            // Use syncData pattern
+            $this->syncData(toModel: true);
             $this->application->refresh();
-            $this->syncData();

Alternatively, document this variation in frontend-patterns.mdc as "Pattern 4: Intermediate Validation and Conflict Checking."

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8c4bfeb and f217fc8.

📒 Files selected for processing (14)
  • .cursor/rules/frontend-patterns.mdc (1 hunks)
  • app/Console/Commands/Cloud/RestoreDatabase.php (1 hunks)
  • app/Livewire/Concerns/SynchronizesModelData.php (0 hunks)
  • app/Livewire/Project/Application/General.php (16 hunks)
  • app/Livewire/Project/Service/EditDomain.php (6 hunks)
  • app/Livewire/Project/Service/FileStorage.php (5 hunks)
  • app/Livewire/Project/Service/ServiceApplicationView.php (7 hunks)
  • app/Livewire/Project/Shared/HealthChecks.php (4 hunks)
  • app/Models/ApplicationSetting.php (1 hunks)
  • config/constants.php (1 hunks)
  • other/nightly/versions.json (1 hunks)
  • resources/views/livewire/project/application/general.blade.php (13 hunks)
  • tests/Unit/ApplicationSettingStaticCastTest.php (1 hunks)
  • versions.json (1 hunks)
💤 Files with no reviewable changes (1)
  • app/Livewire/Concerns/SynchronizesModelData.php
🧰 Additional context used
📓 Path-based instructions (23)
versions.json

📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)

Keep versions.json synchronized with current release versions

Files:

  • versions.json
app/Models/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)

Keep Eloquent domain models in app/Models; models represent core entities (e.g., Application, Server, Service, Team, Project)

app/Models/**/*.php: Define $fillable for mass assignment protection in Eloquent models
Use $casts for attribute casting (e.g., arrays, enums, datetimes) in Eloquent models
Define relationships using Eloquent relation return types (e.g., BelongsTo, HasMany)

app/Models/**/*.php: Define Eloquent relationships using proper relationship methods with return type hints
Prefer Eloquent ORM and relationships over raw queries or DB:: calls
Prevent N+1 queries by using eager loading when appropriate
When creating new models, also create useful factories and seeders

Files:

  • app/Models/ApplicationSetting.php
**/*.php

📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)

**/*.php: Follow PSR-12 coding standards for all PHP code
Format PHP code with Laravel Pint configuration
Run static analysis with PHPStan to ensure type safety in PHP code
Document complex methods with PHPDoc blocks including parameters, return types, and thrown exceptions

**/*.php: Follow PSR-12 PHP coding standards across the codebase
Prefer eager loading and query optimization to prevent N+1 issues in database interactions
Use Laravel best practices for structure, services, and policies

**/*.php: Always use curly braces for control structures in PHP, even for single-line bodies
Use PHP 8 constructor property promotion in __construct() and avoid empty constructors
Always declare explicit return types for functions and methods; add appropriate parameter type hints
Prefer PHPDoc blocks over inline comments; only add inline code comments for very complex logic
When documenting arrays, add useful array shape types in PHPDoc where appropriate
Enum case names should be TitleCase (e.g., FavoritePerson, Monthly)

Files:

  • app/Models/ApplicationSetting.php
  • tests/Unit/ApplicationSettingStaticCastTest.php
  • config/constants.php
  • app/Console/Commands/Cloud/RestoreDatabase.php
  • app/Livewire/Project/Service/EditDomain.php
  • app/Livewire/Project/Shared/HealthChecks.php
  • app/Livewire/Project/Service/FileStorage.php
  • resources/views/livewire/project/application/general.blade.php
  • app/Livewire/Project/Service/ServiceApplicationView.php
  • app/Livewire/Project/Application/General.php
app/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)

Use database transactions to group related write operations for consistency in services/controllers/jobs

Files:

  • app/Models/ApplicationSetting.php
  • app/Console/Commands/Cloud/RestoreDatabase.php
  • app/Livewire/Project/Service/EditDomain.php
  • app/Livewire/Project/Shared/HealthChecks.php
  • app/Livewire/Project/Service/FileStorage.php
  • app/Livewire/Project/Service/ServiceApplicationView.php
  • app/Livewire/Project/Application/General.php
app/Models/**

📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)

Place domain models under app/Models

Files:

  • app/Models/ApplicationSetting.php
app/Models/*.php

📄 CodeRabbit inference engine (.cursor/rules/database-patterns.mdc)

app/Models/*.php: When adding new database columns, update the model's $fillable array to allow mass assignment (e.g., for Model::create() and $model->update())
Use UUID primary keys via HasUuids for distributed systems
Enable soft deletes on models that require audit trails using SoftDeletes
Log model activity using the Spatie LogsActivity trait where auditing is required
Define explicit Eloquent relationships (belongsTo/hasMany/etc.) for navigable associations used by queries and eager loading

Files:

  • app/Models/ApplicationSetting.php
tests/Unit/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)

Place unit tests under tests/Unit and keep them focused on individual classes/methods

tests/Unit/**/*.php: Unit tests (tests/Unit) must not use database connections or model factories
Unit tests must use mocking for models and external dependencies

Files:

  • tests/Unit/ApplicationSettingStaticCastTest.php
tests/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)

Write feature tests for API endpoints using Pest; mock external services and assert JSON responses and side effects

Add tests validating that components respect authorization (e.g., unauthorized users see disabled inputs; checkbox instantSave becomes false)

Include security tests covering SQL injection resistance, XSS validation, and enforcement of team isolation (403 on cross-team access).

Write tests using Pest (feature/unit) and include Laravel Dusk for browser scenarios as needed

Prefer Pest PHP as the primary testing framework for writing tests

Files:

  • tests/Unit/ApplicationSettingStaticCastTest.php
tests/**

📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)

Keep automated tests (Pest/Dusk) under tests

Files:

  • tests/Unit/ApplicationSettingStaticCastTest.php
tests/{Feature,Unit}/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/laravel-boost.mdc)

tests/{Feature,Unit}/**/*.php: All tests must be written using Pest and live under tests/Feature or tests/Unit
Use specific response assertion helpers (e.g., assertForbidden, assertNotFound) instead of generic assertStatus
Use datasets in Pest to reduce duplication where suitable (e.g., validation tests)
Write or update unit/feature tests for every change and run the affected tests

Files:

  • tests/Unit/ApplicationSettingStaticCastTest.php
config/*.php

📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)

Keep application settings in Laravel config files under config/ and load them via config()

Application configuration should reside in config/*.php files

Files:

  • config/constants.php
app/Console/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)

Define Artisan console commands in app/Console

Files:

  • app/Console/Commands/Cloud/RestoreDatabase.php
app/Livewire/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)

Define Livewire components in app/Livewire and keep HTTP/UI concerns there

app/Livewire/**/*.php: Livewire components must authorize access in mount and before actions that mutate state
Expose only necessary public typed properties and register event listeners via the $listeners array in Livewire components

app/Livewire/**/*.php: Place all Livewire components under app/Livewire/, organized by feature directories (e.g., Server/, Project/, Settings/, Team/, Profile/, Security/)
Declare protected $rules and validate with $this->validate() in Livewire form actions
For real-time updates, define getListeners() in Livewire components to register broadcast/event listeners
Use Livewire placeholder() to lazy-load heavy components or sections for performance

Place Livewire components under app/Livewire/ (e.g., Dashboard.php, ActivityMonitor.php, MonacoEditor.php)

Livewire 3 components should use the App\Livewire namespace and lifecycle hooks like mount() and updatedFoo()

Files:

  • app/Livewire/Project/Service/EditDomain.php
  • app/Livewire/Project/Shared/HealthChecks.php
  • app/Livewire/Project/Service/FileStorage.php
  • app/Livewire/Project/Service/ServiceApplicationView.php
  • app/Livewire/Project/Application/General.php
app/Livewire/**

📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)

Implement frontend components as Livewire classes under app/Livewire

Files:

  • app/Livewire/Project/Service/EditDomain.php
  • app/Livewire/Project/Shared/HealthChecks.php
  • app/Livewire/Project/Service/FileStorage.php
  • app/Livewire/Project/Service/ServiceApplicationView.php
  • app/Livewire/Project/Application/General.php
{app/Http/Controllers/**/*.php,app/Livewire/**/*.php}

📄 CodeRabbit inference engine (.cursor/rules/README.mdc)

Authorize sensitive actions with policies (e.g., $this->authorize('deploy', $model)) before invoking services

Files:

  • app/Livewire/Project/Service/EditDomain.php
  • app/Livewire/Project/Shared/HealthChecks.php
  • app/Livewire/Project/Service/FileStorage.php
  • app/Livewire/Project/Service/ServiceApplicationView.php
  • app/Livewire/Project/Application/General.php
.cursor/rules/**/*.mdc

📄 CodeRabbit inference engine (.cursor/rules/self_improve.mdc)

Follow .cursor/rules/cursor_rules.mdc for proper rule formatting and structure

Files:

  • .cursor/rules/frontend-patterns.mdc
.cursor/rules/*.mdc

📄 CodeRabbit inference engine (.cursor/rules/cursor_rules.mdc)

.cursor/rules/*.mdc: Each rule file must begin with front matter containing description, globs, and alwaysApply fields
Structure the rule body with bolded main points and supporting sub-points, including examples and explanations
Use filename links for file references
Use language-specific code blocks for examples
Include both DO and DON'T examples in code blocks
Start each rule with a high-level overview
Include specific, actionable requirements in the rule
Show examples of correct implementation
Reference existing code when possible
Keep rules DRY by referencing other rules rather than duplicating content
Update rules when new patterns emerge
Add examples from the actual codebase to rules
Remove outdated patterns from rules
Cross-reference related rules within the repository
Use bullet points for clarity
Keep descriptions concise
Include both DO and DON'T examples in rules
Prefer referencing actual code over theoretical examples
Use consistent formatting across all rules

Files:

  • .cursor/rules/frontend-patterns.mdc
{.cursor/rules/*.mdc,CLAUDE.md,.AI_INSTRUCTIONS_SYNC.md}

📄 CodeRabbit inference engine (.cursor/rules/cursor_rules.mdc)

Reflect changes in .cursor/rules that affect core workflows or patterns in CLAUDE.md and follow .AI_INSTRUCTIONS_SYNC.md for synchronization

Files:

  • .cursor/rules/frontend-patterns.mdc
resources/views/**/*.blade.php

📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)

Use semantic Tailwind CSS classes and consistent spacing in Blade templates

resources/views/**/*.blade.php: In Blade views, prefer using x-forms components with canGate and :canResource instead of wrapping elements in @can/@else blocks
Remove legacy @can/@else blocks around individual form inputs/buttons and migrate to the single-line component pattern
Choose gates consistently in views: use update for configuration changes, deploy for operational actions, view for read-only access, and delete for destructive actions
Always pass the specific resource to :canResource (e.g., :canResource="$application", "$service", "$server"), and use team context for creation permissions (e.g., :canResource="auth()->user()->currentTeam" with canGate="createAnyResource")
Only set autoDisable="false" when also providing explicit :disabled logic on the component
Use single-line authorized components for forms (inputs, selects, checkboxes, buttons) to reduce duplication (e.g., <x-forms.input canGate="update" :canResource="$resource" ... />)

resources/views/**/*.blade.php: Prefer Alpine.js directives (x-data, x-on, x-show, x-model, x-init) for lightweight interactivity in Blade views
Use enhanced <x-forms.*> components with canGate and canResource for authorization instead of @can/@else blocks
When protecting forms, pass canGate and :canResource to all x-forms components; rely on autoDisable=true for unauthorized users
Apply Tailwind responsive utilities (e.g., grid breakpoints) for mobile-first layouts
Support dark mode using Tailwind dark: variants on relevant elements
Ensure interactive controls include appropriate ARIA attributes (e.g., aria-label, aria-describedby) for accessibility

resources/views/**/*.blade.php: In Blade views, prefer x-forms.* components with canGate and :canResource for authorization (autoDisable defaults to true) instead of manual permission blocks.
Do not wrap x-forms.* components in @can/@else to toggle disabled state; use component-level canGate/:can...

Files:

  • resources/views/livewire/project/application/general.blade.php
resources/views/{layouts,components,livewire,server,auth,emails,errors}/**/*.blade.php

📄 CodeRabbit inference engine (.cursor/rules/frontend-patterns.mdc)

Organize Blade templates into the specified folders: layouts/, components/, livewire/, and feature-specific directories server/, auth/, emails/, errors/

Files:

  • resources/views/livewire/project/application/general.blade.php
resources/**

📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)

Store frontend assets and views under resources

Files:

  • resources/views/livewire/project/application/general.blade.php
resources/views/livewire/**/*.blade.php

📄 CodeRabbit inference engine (.cursor/rules/laravel-boost.mdc)

Livewire components must have a single root element; use wire:key in loops and wire:loading/wire:dirty for UX

Files:

  • resources/views/livewire/project/application/general.blade.php
resources/**/*.{blade.php,vue}

📄 CodeRabbit inference engine (.cursor/rules/laravel-boost.mdc)

Use Tailwind gap utilities for spacing lists instead of margins when listing items

Files:

  • resources/views/livewire/project/application/general.blade.php
🧠 Learnings (27)
📓 Common learnings
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/frontend-patterns.mdc:0-0
Timestamp: 2025-08-27T15:03:30.794Z
Learning: Applies to app/Livewire/**/*.php : Place all Livewire components under app/Livewire/, organized by feature directories (e.g., Server/, Project/, Settings/, Team/, Profile/, Security/)
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/project-overview.mdc:0-0
Timestamp: 2025-08-27T15:04:22.911Z
Learning: Applies to app/Livewire/** : Implement frontend components as Livewire classes under app/Livewire
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/technology-stack.mdc:0-0
Timestamp: 2025-08-27T15:06:41.387Z
Learning: Applies to app/Livewire/**/*.php : Place Livewire components under app/Livewire/ (e.g., Dashboard.php, ActivityMonitor.php, MonacoEditor.php)
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/laravel-boost.mdc:0-0
Timestamp: 2025-10-15T09:16:25.875Z
Learning: Applies to app/Livewire/**/*.php : Livewire 3 components should use the App\Livewire namespace and lifecycle hooks like mount() and updatedFoo()
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/development-workflow.mdc:0-0
Timestamp: 2025-08-27T15:01:58.710Z
Learning: Applies to app/Models/**/*.php : Use $casts for attribute casting (e.g., arrays, enums, datetimes) in Eloquent models
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/application-architecture.mdc:0-0
Timestamp: 2025-08-27T14:59:11.004Z
Learning: Applies to app/Livewire/**/*.php : Define Livewire components in app/Livewire and keep HTTP/UI concerns there
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/development-workflow.mdc:0-0
Timestamp: 2025-08-27T15:01:58.710Z
Learning: Applies to app/Livewire/**/*.php : Expose only necessary public typed properties and register event listeners via the $listeners array in Livewire components
📚 Learning: 2025-08-27T15:01:58.710Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/development-workflow.mdc:0-0
Timestamp: 2025-08-27T15:01:58.710Z
Learning: Applies to versions.json : Keep versions.json synchronized with current release versions

Applied to files:

  • versions.json
📚 Learning: 2025-08-27T15:01:58.710Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/development-workflow.mdc:0-0
Timestamp: 2025-08-27T15:01:58.710Z
Learning: Applies to app/Models/**/*.php : Use $casts for attribute casting (e.g., arrays, enums, datetimes) in Eloquent models

Applied to files:

  • app/Models/ApplicationSetting.php
  • tests/Unit/ApplicationSettingStaticCastTest.php
📚 Learning: 2025-08-27T14:59:11.004Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/application-architecture.mdc:0-0
Timestamp: 2025-08-27T14:59:11.004Z
Learning: Applies to app/Models/**/*.php : Keep Eloquent domain models in app/Models; models represent core entities (e.g., Application, Server, Service, Team, Project)

Applied to files:

  • app/Livewire/Project/Service/EditDomain.php
  • app/Livewire/Project/Service/FileStorage.php
📚 Learning: 2025-08-27T15:01:58.710Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/development-workflow.mdc:0-0
Timestamp: 2025-08-27T15:01:58.710Z
Learning: Applies to app/Livewire/**/*.php : Livewire components must authorize access in mount and before actions that mutate state

Applied to files:

  • app/Livewire/Project/Service/EditDomain.php
  • app/Livewire/Project/Shared/HealthChecks.php
  • .cursor/rules/frontend-patterns.mdc
  • app/Livewire/Project/Service/FileStorage.php
  • app/Livewire/Project/Service/ServiceApplicationView.php
📚 Learning: 2025-08-27T14:59:11.004Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/application-architecture.mdc:0-0
Timestamp: 2025-08-27T14:59:11.004Z
Learning: Applies to app/Livewire/**/*.php : Define Livewire components in app/Livewire and keep HTTP/UI concerns there

Applied to files:

  • app/Livewire/Project/Service/EditDomain.php
  • app/Livewire/Project/Shared/HealthChecks.php
  • .cursor/rules/frontend-patterns.mdc
  • app/Livewire/Project/Service/FileStorage.php
  • app/Livewire/Project/Service/ServiceApplicationView.php
📚 Learning: 2025-10-15T09:13:00.453Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/README.mdc:0-0
Timestamp: 2025-10-15T09:13:00.453Z
Learning: Applies to {app/Http/Controllers/**/*.php,app/Livewire/**/*.php} : Authorize sensitive actions with policies (e.g., $this->authorize('deploy', $model)) before invoking services

Applied to files:

  • app/Livewire/Project/Service/EditDomain.php
  • app/Livewire/Project/Shared/HealthChecks.php
  • app/Livewire/Project/Service/FileStorage.php
  • app/Livewire/Project/Service/ServiceApplicationView.php
📚 Learning: 2025-08-27T15:03:30.794Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/frontend-patterns.mdc:0-0
Timestamp: 2025-08-27T15:03:30.794Z
Learning: Applies to app/Livewire/**/*.php : Declare protected $rules and validate with $this->validate() in Livewire form actions

Applied to files:

  • app/Livewire/Project/Service/EditDomain.php
  • app/Livewire/Project/Shared/HealthChecks.php
  • .cursor/rules/frontend-patterns.mdc
  • app/Livewire/Project/Service/FileStorage.php
  • app/Livewire/Project/Service/ServiceApplicationView.php
  • app/Livewire/Project/Application/General.php
📚 Learning: 2025-10-15T09:16:25.875Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/laravel-boost.mdc:0-0
Timestamp: 2025-10-15T09:16:25.875Z
Learning: Applies to app/Livewire/**/*.php : Livewire 3 components should use the App\Livewire namespace and lifecycle hooks like mount() and updatedFoo()

Applied to files:

  • app/Livewire/Project/Service/EditDomain.php
  • app/Livewire/Project/Shared/HealthChecks.php
  • .cursor/rules/frontend-patterns.mdc
  • app/Livewire/Project/Service/FileStorage.php
  • app/Livewire/Project/Service/ServiceApplicationView.php
  • app/Livewire/Project/Application/General.php
📚 Learning: 2025-08-27T15:04:22.911Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/project-overview.mdc:0-0
Timestamp: 2025-08-27T15:04:22.911Z
Learning: Applies to app/Livewire/** : Implement frontend components as Livewire classes under app/Livewire

Applied to files:

  • app/Livewire/Project/Service/EditDomain.php
  • .cursor/rules/frontend-patterns.mdc
  • app/Livewire/Project/Service/FileStorage.php
  • resources/views/livewire/project/application/general.blade.php
  • app/Livewire/Project/Service/ServiceApplicationView.php
📚 Learning: 2025-08-27T14:58:10.424Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/api-and-routing.mdc:0-0
Timestamp: 2025-08-27T14:58:10.424Z
Learning: Applies to routes/api.php : Register custom route model bindings for 'application' (by uuid or id) and 'team_application' (scoped to team)

Applied to files:

  • app/Livewire/Project/Service/EditDomain.php
📚 Learning: 2025-08-27T15:05:39.010Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/security-patterns.mdc:0-0
Timestamp: 2025-08-27T15:05:39.010Z
Learning: Applies to app/Http/{Controllers,Livewire}/**/*.php : Back-end methods that mutate state for custom components must enforce authorization (e.g., $this->authorize('gate', $resource) or Gate::authorize).

Applied to files:

  • app/Livewire/Project/Shared/HealthChecks.php
  • app/Livewire/Project/Service/FileStorage.php
📚 Learning: 2025-08-27T15:03:30.794Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/frontend-patterns.mdc:0-0
Timestamp: 2025-08-27T15:03:30.794Z
Learning: Applies to app/Livewire/**/*.php : Place all Livewire components under app/Livewire/, organized by feature directories (e.g., Server/, Project/, Settings/, Team/, Profile/, Security/)

Applied to files:

  • .cursor/rules/frontend-patterns.mdc
  • app/Livewire/Project/Service/FileStorage.php
  • resources/views/livewire/project/application/general.blade.php
  • app/Livewire/Project/Service/ServiceApplicationView.php
  • app/Livewire/Project/Application/General.php
📚 Learning: 2025-10-15T09:13:35.928Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/cursor_rules.mdc:0-0
Timestamp: 2025-10-15T09:13:35.928Z
Learning: Applies to {.cursor/rules/*.mdc,CLAUDE.md,.AI_INSTRUCTIONS_SYNC.md} : Reflect changes in .cursor/rules that affect core workflows or patterns in CLAUDE.md and follow .AI_INSTRUCTIONS_SYNC.md for synchronization

Applied to files:

  • .cursor/rules/frontend-patterns.mdc
📚 Learning: 2025-08-27T15:06:41.387Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/technology-stack.mdc:0-0
Timestamp: 2025-08-27T15:06:41.387Z
Learning: Applies to app/Livewire/**/*.php : Place Livewire components under app/Livewire/ (e.g., Dashboard.php, ActivityMonitor.php, MonacoEditor.php)

Applied to files:

  • .cursor/rules/frontend-patterns.mdc
  • app/Livewire/Project/Service/FileStorage.php
  • resources/views/livewire/project/application/general.blade.php
  • app/Livewire/Project/Service/ServiceApplicationView.php
  • app/Livewire/Project/Application/General.php
📚 Learning: 2025-08-27T15:02:37.804Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/form-components.mdc:0-0
Timestamp: 2025-08-27T15:02:37.804Z
Learning: Applies to resources/views/**/*.blade.php : Use single-line authorized components for forms (inputs, selects, checkboxes, buttons) to reduce duplication (e.g., <x-forms.input canGate="update" :canResource="$resource" ... />)

Applied to files:

  • .cursor/rules/frontend-patterns.mdc
  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-10-15T09:16:25.875Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/laravel-boost.mdc:0-0
Timestamp: 2025-10-15T09:16:25.875Z
Learning: Applies to resources/views/livewire/**/*.blade.php : Livewire components must have a single root element; use wire:key in loops and wire:loading/wire:dirty for UX

Applied to files:

  • .cursor/rules/frontend-patterns.mdc
📚 Learning: 2025-08-27T15:02:37.804Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/form-components.mdc:0-0
Timestamp: 2025-08-27T15:02:37.804Z
Learning: Applies to app/View/Components/Forms/{Input,Select,Textarea,Checkbox,Button}.php : Form component classes must define public properties: ?string $canGate = null, mixed $canResource = null, bool $autoDisable = true

Applied to files:

  • .cursor/rules/frontend-patterns.mdc
  • resources/views/livewire/project/application/general.blade.php
  • app/Livewire/Project/Application/General.php
📚 Learning: 2025-08-27T15:04:22.911Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/project-overview.mdc:0-0
Timestamp: 2025-08-27T15:04:22.911Z
Learning: Use Laravel for the backend with Livewire for the frontend

Applied to files:

  • app/Livewire/Project/Service/FileStorage.php
  • app/Livewire/Project/Service/ServiceApplicationView.php
📚 Learning: 2025-08-27T15:03:30.794Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/frontend-patterns.mdc:0-0
Timestamp: 2025-08-27T15:03:30.794Z
Learning: Applies to resources/views/{layouts,components,livewire,server,auth,emails,errors}/**/*.blade.php : Organize Blade templates into the specified folders: layouts/, components/, livewire/, and feature-specific directories server/, auth/, emails/, errors/

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-08-27T15:02:37.804Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/form-components.mdc:0-0
Timestamp: 2025-08-27T15:02:37.804Z
Learning: Applies to resources/views/**/*.blade.php : Remove legacy can/else blocks around individual form inputs/buttons and migrate to the single-line component pattern

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-08-27T15:05:39.010Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/security-patterns.mdc:0-0
Timestamp: 2025-08-27T15:05:39.010Z
Learning: Applies to resources/views/**/*.blade.php : Do not wrap x-forms.* components in can/else to toggle disabled state; use component-level canGate/:canResource instead.

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-08-27T15:05:39.010Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/security-patterns.mdc:0-0
Timestamp: 2025-08-27T15:05:39.010Z
Learning: Applies to resources/views/**/*.blade.php : For custom interactive components not using x-forms.* (e.g., Alpine.js widgets), wrap with can('gate', $resource) and provide a disabled/readonly fallback in else with opacity-50 and cursor-not-allowed styling.

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-08-27T15:05:39.010Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/security-patterns.mdc:0-0
Timestamp: 2025-08-27T15:05:39.010Z
Learning: Applies to app/View/Components/Forms/Checkbox*.php : When authorization disables a Checkbox component, also force instantSave to false to prevent unauthorized interactions.

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-10-15T09:16:25.875Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/laravel-boost.mdc:0-0
Timestamp: 2025-10-15T09:16:25.875Z
Learning: Applies to resources/views/components/layouts/app.blade.php : Use the components.layouts.app view as the default layout for Livewire 3 components

Applied to files:

  • app/Livewire/Project/Service/ServiceApplicationView.php
📚 Learning: 2025-08-27T15:01:10.040Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/deployment-architecture.mdc:0-0
Timestamp: 2025-08-27T15:01:10.040Z
Learning: Applies to app/Services/ConfigurationGenerator.php : Generate deployment configuration via app/Services/ConfigurationGenerator.php rather than hardcoding in actions

Applied to files:

  • app/Livewire/Project/Application/General.php
📚 Learning: 2025-08-27T15:01:10.040Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/deployment-architecture.mdc:0-0
Timestamp: 2025-08-27T15:01:10.040Z
Learning: Applies to app/Services/DockerImageParser.php : Use app/Services/DockerImageParser.php to parse and validate Docker image references

Applied to files:

  • app/Livewire/Project/Application/General.php
🧬 Code graph analysis (6)
tests/Unit/ApplicationSettingStaticCastTest.php (1)
app/Models/ApplicationSetting.php (1)
  • ApplicationSetting (8-48)
app/Livewire/Project/Service/EditDomain.php (4)
app/Livewire/Project/Service/FileStorage.php (1)
  • syncData (69-84)
app/Livewire/Project/Service/ServiceApplicationView.php (1)
  • syncData (138-165)
app/Livewire/Project/Application/General.php (1)
  • syncData (372-475)
app/Models/InstanceSettings.php (1)
  • fqdn (53-65)
app/Livewire/Project/Shared/HealthChecks.php (6)
app/Livewire/Project/Service/EditDomain.php (2)
  • mount (32-37)
  • syncData (39-52)
app/Livewire/Project/Service/FileStorage.php (3)
  • mount (54-67)
  • syncData (69-84)
  • instantSave (194-197)
app/Livewire/Project/Service/ServiceApplicationView.php (3)
  • mount (127-136)
  • syncData (138-165)
  • instantSave (69-77)
app/Livewire/Source/Github/Change.php (3)
  • mount (193-248)
  • syncData (105-144)
  • instantSave (353-366)
app/Livewire/Project/Shared/ResourceLimits.php (2)
  • mount (77-80)
  • syncData (54-75)
app/Livewire/Project/Service/Database.php (3)
  • mount (58-71)
  • syncData (73-92)
  • instantSave (180-211)
app/Livewire/Project/Service/FileStorage.php (3)
app/Livewire/Project/Service/EditDomain.php (1)
  • syncData (39-52)
app/Livewire/Project/Service/ServiceApplicationView.php (1)
  • syncData (138-165)
app/Models/LocalFileVolume.php (1)
  • saveStorageOnServer (109-180)
app/Livewire/Project/Service/ServiceApplicationView.php (8)
app/Models/Application.php (3)
  • isLogDrainEnabled (976-979)
  • isGzipEnabled (394-397)
  • isStripprefixEnabled (389-392)
app/Livewire/Project/Service/EditDomain.php (1)
  • syncData (39-52)
app/Livewire/Project/Shared/HealthChecks.php (1)
  • syncData (77-114)
app/Livewire/Project/Application/General.php (1)
  • syncData (372-475)
app/Livewire/Project/Service/StackForm.php (1)
  • syncData (69-86)
app/Livewire/Project/Service/EditCompose.php (1)
  • syncData (50-61)
app/Livewire/Project/Service/Database.php (1)
  • syncData (73-92)
bootstrap/helpers/shared.php (1)
  • handleError (190-224)
app/Livewire/Project/Application/General.php (5)
app/Livewire/Project/Database/Clickhouse/General.php (2)
  • General (15-219)
  • syncData (106-138)
app/Models/Application.php (10)
  • baseDirectory (594-599)
  • publishDirectory (458-463)
  • portsMappings (601-606)
  • customNetworkAliases (217-265)
  • dockerfileLocation (560-575)
  • dockerComposeLocation (577-592)
  • customNginxConfiguration (726-732)
  • settings (438-441)
  • parseContainerLabels (1578-1596)
  • loadComposeFile (1459-1576)
app/Livewire/Project/Service/StackForm.php (1)
  • syncData (69-86)
app/Livewire/Project/Application/Source.php (1)
  • syncData (65-85)
app/Livewire/Project/Application/Advanced.php (2)
  • syncData (88-138)
  • resetDefaultLabels (140-148)
🔇 Additional comments (7)
versions.json (1)

4-4: LGTM! Version bumps are consistent.

The v4 and nightly version increments align with the beta release progression documented in config/constants.php.

Also applies to: 7-7

other/nightly/versions.json (1)

4-4: LGTM! Nightly versions synchronized.

The version jumps bring this nightly configuration in sync with the main versions.json file.

Also applies to: 7-7

config/constants.php (1)

5-5: LGTM! Configuration version updated.

The version bump aligns with the release metadata in versions.json.

tests/Unit/ApplicationSettingStaticCastTest.php (2)

12-74: LGTM! Comprehensive boolean casting tests.

The tests thoroughly validate boolean casting behavior for various input types (boolean, string, integer) and confirm that the casts configuration is properly defined.


76-105: LGTM! Complete validation of all boolean fields.

The test verifies all 15 boolean fields are properly cast, matching the casts array in ApplicationSetting.php.

app/Livewire/Project/Service/EditDomain.php (1)

39-52: LGTM! syncData() implementation follows the documented pattern.

The method correctly implements bidirectional synchronization with validation when syncing to the model and simple assignment when syncing from the model.

resources/views/livewire/project/application/general.blade.php (1)

26-26: All camelCase template bindings have corresponding component properties—no mismatches found.

The verification confirms the systematic renaming from snake_case to camelCase has been correctly applied. All 41 unique bindings in the template (buildPack, dockerRegistryImageName, isStatic, parsedServiceDomains, etc.) are present in the Livewire component's public properties. The dynamic array access pattern parsedServiceDomains.{{ str($serviceName)... }}.domain correctly maps to the component's parsedServiceDomains property.

- Fix SPA toggle not triggering nginx configuration regeneration by capturing old value before syncData
- Fix similar issue with is_http_basic_auth_enabled using value comparison instead of isDirty
- Remove redundant application settings save() call
- Add confirmation modal to nginx generation button to prevent accidental overwrites
- Pass correct type parameter (spa/static) to generateNginxConfiguration method
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: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f217fc8 and 7b589ab.

📒 Files selected for processing (2)
  • app/Livewire/Project/Application/General.php (16 hunks)
  • resources/views/livewire/project/application/general.blade.php (12 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
**/*.php

📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)

**/*.php: Follow PSR-12 coding standards for all PHP code
Format PHP code with Laravel Pint configuration
Run static analysis with PHPStan to ensure type safety in PHP code
Document complex methods with PHPDoc blocks including parameters, return types, and thrown exceptions

**/*.php: Follow PSR-12 PHP coding standards across the codebase
Prefer eager loading and query optimization to prevent N+1 issues in database interactions
Use Laravel best practices for structure, services, and policies

**/*.php: Always use curly braces for control structures in PHP, even for single-line bodies
Use PHP 8 constructor property promotion in __construct() and avoid empty constructors
Always declare explicit return types for functions and methods; add appropriate parameter type hints
Prefer PHPDoc blocks over inline comments; only add inline code comments for very complex logic
When documenting arrays, add useful array shape types in PHPDoc where appropriate
Enum case names should be TitleCase (e.g., FavoritePerson, Monthly)

Files:

  • resources/views/livewire/project/application/general.blade.php
  • app/Livewire/Project/Application/General.php
resources/views/**/*.blade.php

📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)

Use semantic Tailwind CSS classes and consistent spacing in Blade templates

resources/views/**/*.blade.php: In Blade views, prefer using x-forms components with canGate and :canResource instead of wrapping elements in @can/@else blocks
Remove legacy @can/@else blocks around individual form inputs/buttons and migrate to the single-line component pattern
Choose gates consistently in views: use update for configuration changes, deploy for operational actions, view for read-only access, and delete for destructive actions
Always pass the specific resource to :canResource (e.g., :canResource="$application", "$service", "$server"), and use team context for creation permissions (e.g., :canResource="auth()->user()->currentTeam" with canGate="createAnyResource")
Only set autoDisable="false" when also providing explicit :disabled logic on the component
Use single-line authorized components for forms (inputs, selects, checkboxes, buttons) to reduce duplication (e.g., <x-forms.input canGate="update" :canResource="$resource" ... />)

resources/views/**/*.blade.php: Prefer Alpine.js directives (x-data, x-on, x-show, x-model, x-init) for lightweight interactivity in Blade views
Use enhanced <x-forms.*> components with canGate and canResource for authorization instead of @can/@else blocks
When protecting forms, pass canGate and :canResource to all x-forms components; rely on autoDisable=true for unauthorized users
Apply Tailwind responsive utilities (e.g., grid breakpoints) for mobile-first layouts
Support dark mode using Tailwind dark: variants on relevant elements
Ensure interactive controls include appropriate ARIA attributes (e.g., aria-label, aria-describedby) for accessibility

resources/views/**/*.blade.php: In Blade views, prefer x-forms.* components with canGate and :canResource for authorization (autoDisable defaults to true) instead of manual permission blocks.
Do not wrap x-forms.* components in @can/@else to toggle disabled state; use component-level canGate/:can...

Files:

  • resources/views/livewire/project/application/general.blade.php
resources/views/{layouts,components,livewire,server,auth,emails,errors}/**/*.blade.php

📄 CodeRabbit inference engine (.cursor/rules/frontend-patterns.mdc)

Organize Blade templates into the specified folders: layouts/, components/, livewire/, and feature-specific directories server/, auth/, emails/, errors/

Files:

  • resources/views/livewire/project/application/general.blade.php
resources/**

📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)

Store frontend assets and views under resources

Files:

  • resources/views/livewire/project/application/general.blade.php
resources/views/livewire/**/*.blade.php

📄 CodeRabbit inference engine (.cursor/rules/laravel-boost.mdc)

Livewire components must have a single root element; use wire:key in loops and wire:loading/wire:dirty for UX

Files:

  • resources/views/livewire/project/application/general.blade.php
resources/**/*.{blade.php,vue}

📄 CodeRabbit inference engine (.cursor/rules/laravel-boost.mdc)

Use Tailwind gap utilities for spacing lists instead of margins when listing items

Files:

  • resources/views/livewire/project/application/general.blade.php
app/Livewire/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)

Define Livewire components in app/Livewire and keep HTTP/UI concerns there

app/Livewire/**/*.php: Livewire components must authorize access in mount and before actions that mutate state
Expose only necessary public typed properties and register event listeners via the $listeners array in Livewire components

app/Livewire/**/*.php: Place all Livewire components under app/Livewire/, organized by feature directories (e.g., Server/, Project/, Settings/, Team/, Profile/, Security/)
Declare protected $rules and validate with $this->validate() in Livewire form actions
For real-time updates, define getListeners() in Livewire components to register broadcast/event listeners
Use Livewire placeholder() to lazy-load heavy components or sections for performance

Place Livewire components under app/Livewire/ (e.g., Dashboard.php, ActivityMonitor.php, MonacoEditor.php)

Livewire 3 components should use the App\Livewire namespace and lifecycle hooks like mount() and updatedFoo()

Files:

  • app/Livewire/Project/Application/General.php
app/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)

Use database transactions to group related write operations for consistency in services/controllers/jobs

Files:

  • app/Livewire/Project/Application/General.php
app/Livewire/**

📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)

Implement frontend components as Livewire classes under app/Livewire

Files:

  • app/Livewire/Project/Application/General.php
{app/Http/Controllers/**/*.php,app/Livewire/**/*.php}

📄 CodeRabbit inference engine (.cursor/rules/README.mdc)

Authorize sensitive actions with policies (e.g., $this->authorize('deploy', $model)) before invoking services

Files:

  • app/Livewire/Project/Application/General.php
🧠 Learnings (16)
📓 Common learnings
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/frontend-patterns.mdc:0-0
Timestamp: 2025-08-27T15:03:30.794Z
Learning: Applies to app/Livewire/**/*.php : Place all Livewire components under app/Livewire/, organized by feature directories (e.g., Server/, Project/, Settings/, Team/, Profile/, Security/)
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/technology-stack.mdc:0-0
Timestamp: 2025-08-27T15:06:41.387Z
Learning: Applies to app/Livewire/**/*.php : Place Livewire components under app/Livewire/ (e.g., Dashboard.php, ActivityMonitor.php, MonacoEditor.php)
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/development-workflow.mdc:0-0
Timestamp: 2025-08-27T15:01:58.710Z
Learning: Applies to app/Models/**/*.php : Use $casts for attribute casting (e.g., arrays, enums, datetimes) in Eloquent models
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/project-overview.mdc:0-0
Timestamp: 2025-08-27T15:04:22.911Z
Learning: Applies to app/Livewire/** : Implement frontend components as Livewire classes under app/Livewire
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/laravel-boost.mdc:0-0
Timestamp: 2025-10-15T09:16:25.875Z
Learning: Applies to app/Livewire/**/*.php : Livewire 3 components should use the App\Livewire namespace and lifecycle hooks like mount() and updatedFoo()
📚 Learning: 2025-08-27T15:03:30.794Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/frontend-patterns.mdc:0-0
Timestamp: 2025-08-27T15:03:30.794Z
Learning: Applies to app/Livewire/**/*.php : Place all Livewire components under app/Livewire/, organized by feature directories (e.g., Server/, Project/, Settings/, Team/, Profile/, Security/)

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-08-27T15:06:41.387Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/technology-stack.mdc:0-0
Timestamp: 2025-08-27T15:06:41.387Z
Learning: Applies to app/Livewire/**/*.php : Place Livewire components under app/Livewire/ (e.g., Dashboard.php, ActivityMonitor.php, MonacoEditor.php)

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-08-27T15:04:22.911Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/project-overview.mdc:0-0
Timestamp: 2025-08-27T15:04:22.911Z
Learning: Applies to app/Livewire/** : Implement frontend components as Livewire classes under app/Livewire

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-08-27T15:03:30.794Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/frontend-patterns.mdc:0-0
Timestamp: 2025-08-27T15:03:30.794Z
Learning: Applies to resources/views/{layouts,components,livewire,server,auth,emails,errors}/**/*.blade.php : Organize Blade templates into the specified folders: layouts/, components/, livewire/, and feature-specific directories server/, auth/, emails/, errors/

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-08-27T14:59:11.004Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/application-architecture.mdc:0-0
Timestamp: 2025-08-27T14:59:11.004Z
Learning: Applies to app/Livewire/**/*.php : Define Livewire components in app/Livewire and keep HTTP/UI concerns there

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-10-15T09:16:25.875Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/laravel-boost.mdc:0-0
Timestamp: 2025-10-15T09:16:25.875Z
Learning: Applies to app/Livewire/**/*.php : Livewire 3 components should use the App\Livewire namespace and lifecycle hooks like mount() and updatedFoo()

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-08-27T15:02:37.804Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/form-components.mdc:0-0
Timestamp: 2025-08-27T15:02:37.804Z
Learning: Applies to resources/views/**/*.blade.php : Remove legacy can/else blocks around individual form inputs/buttons and migrate to the single-line component pattern

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-08-27T15:02:37.804Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/form-components.mdc:0-0
Timestamp: 2025-08-27T15:02:37.804Z
Learning: Applies to resources/views/**/*.blade.php : Use single-line authorized components for forms (inputs, selects, checkboxes, buttons) to reduce duplication (e.g., <x-forms.input canGate="update" :canResource="$resource" ... />)

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-08-27T15:05:39.010Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/security-patterns.mdc:0-0
Timestamp: 2025-08-27T15:05:39.010Z
Learning: Applies to resources/views/**/*.blade.php : Do not wrap x-forms.* components in can/else to toggle disabled state; use component-level canGate/:canResource instead.

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-08-27T15:02:37.804Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/form-components.mdc:0-0
Timestamp: 2025-08-27T15:02:37.804Z
Learning: Applies to app/View/Components/Forms/{Input,Select,Textarea,Checkbox,Button}.php : Form component classes must define public properties: ?string $canGate = null, mixed $canResource = null, bool $autoDisable = true

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
  • app/Livewire/Project/Application/General.php
📚 Learning: 2025-08-27T15:05:39.010Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/security-patterns.mdc:0-0
Timestamp: 2025-08-27T15:05:39.010Z
Learning: Applies to resources/views/**/*.blade.php : For custom interactive components not using x-forms.* (e.g., Alpine.js widgets), wrap with can('gate', $resource) and provide a disabled/readonly fallback in else with opacity-50 and cursor-not-allowed styling.

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-08-27T15:05:39.010Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/security-patterns.mdc:0-0
Timestamp: 2025-08-27T15:05:39.010Z
Learning: Applies to app/View/Components/Forms/Checkbox*.php : When authorization disables a Checkbox component, also force instantSave to false to prevent unauthorized interactions.

Applied to files:

  • resources/views/livewire/project/application/general.blade.php
📚 Learning: 2025-08-27T15:03:30.794Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/frontend-patterns.mdc:0-0
Timestamp: 2025-08-27T15:03:30.794Z
Learning: Applies to app/Livewire/**/*.php : Declare protected $rules and validate with $this->validate() in Livewire form actions

Applied to files:

  • app/Livewire/Project/Application/General.php
📚 Learning: 2025-08-27T15:01:10.040Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/deployment-architecture.mdc:0-0
Timestamp: 2025-08-27T15:01:10.040Z
Learning: Applies to app/Services/ConfigurationGenerator.php : Generate deployment configuration via app/Services/ConfigurationGenerator.php rather than hardcoding in actions

Applied to files:

  • app/Livewire/Project/Application/General.php
📚 Learning: 2025-08-27T15:01:10.040Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/deployment-architecture.mdc:0-0
Timestamp: 2025-08-27T15:01:10.040Z
Learning: Applies to app/Services/DockerImageParser.php : Use app/Services/DockerImageParser.php to parse and validate Docker image references

Applied to files:

  • app/Livewire/Project/Application/General.php
🧬 Code graph analysis (1)
app/Livewire/Project/Application/General.php (5)
app/Models/Application.php (9)
  • publishDirectory (458-463)
  • customNetworkAliases (217-265)
  • dockerfileLocation (560-575)
  • dockerComposeLocation (577-592)
  • customNginxConfiguration (726-732)
  • settings (438-441)
  • parseContainerLabels (1578-1596)
  • type (453-456)
  • loadComposeFile (1459-1576)
app/Livewire/Project/Application/Source.php (1)
  • syncData (65-85)
app/Livewire/Project/Application/Advanced.php (1)
  • syncData (88-138)
bootstrap/helpers/shared.php (1)
  • defaultNginxConfiguration (2976-3027)
bootstrap/helpers/docker.php (2)
  • generateLabelsApplication (595-737)
  • get_port_from_dockerfile (174-190)
⏰ 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)

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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: 0

Caution

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

⚠️ Outside diff range comments (1)
app/Livewire/Project/Application/General.php (1)

825-879: Post-sync property modifications bypass validation and break the syncData pattern.

After calling syncData(toModel: true) at line 825, the code modifies several properties directly (lines 861-879): customDockerRunOptions, portsExposes, baseDirectory, and publishDirectory. These changes bypass validation, aren't synced to component properties, and violate the two-way sync contract established by syncData. Consider moving these transformations before the syncData(toModel: true) call so they're validated and properly synced, or explicitly call syncData(toModel: true) again after modifications.

♻️ Duplicate comments (1)
app/Livewire/Project/Application/General.php (1)

909-909: Prevent TypeError by guarding base64_encode against null.

Line 909 encodes $this->customLabels without checking for null, even though the property is nullable and may not be regenerated at lines 839-843 if conditions aren't met. This will throw a TypeError in PHP 8 when users save forms without custom labels.

Apply this diff to guard the encoding:

-            $this->application->custom_labels = base64_encode($this->customLabels);
+            $this->application->custom_labels = is_null($this->customLabels)
+                ? null
+                : base64_encode($this->customLabels);
🧹 Nitpick comments (2)
app/Livewire/Project/Application/General.php (2)

25-155: Duplicate validation rules create maintenance risk.

Validation logic is declared both via #[Validate] attributes (lines 25-155) and in the rules() method (lines 179-227). Maintaining two sets of identical rules increases the risk of them drifting out of sync during future updates. Consider removing the rules() method and relying solely on the #[Validate] attributes, or document why both are necessary.

Also applies to: 179-227


623-679: Simplify updatedBuildPack to use consistent syncData pattern.

The method mixes approaches: it directly updates both component properties (e.g., $this->isStatic = false at line 640) and model properties (e.g., $this->application->settings->is_static = false at line 641), then calls submit() at line 677 which syncs again via syncData(toModel: true). For consistency and maintainability, consider updating only component properties and relying on the final submit() call to persist changes via syncData, eliminating the redundant assignments.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b589ab and a45e674.

📒 Files selected for processing (1)
  • app/Livewire/Project/Application/General.php (16 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
app/Livewire/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/application-architecture.mdc)

Define Livewire components in app/Livewire and keep HTTP/UI concerns there

app/Livewire/**/*.php: Livewire components must authorize access in mount and before actions that mutate state
Expose only necessary public typed properties and register event listeners via the $listeners array in Livewire components

app/Livewire/**/*.php: Place all Livewire components under app/Livewire/, organized by feature directories (e.g., Server/, Project/, Settings/, Team/, Profile/, Security/)
Declare protected $rules and validate with $this->validate() in Livewire form actions
For real-time updates, define getListeners() in Livewire components to register broadcast/event listeners
Use Livewire placeholder() to lazy-load heavy components or sections for performance

Place Livewire components under app/Livewire/ (e.g., Dashboard.php, ActivityMonitor.php, MonacoEditor.php)

Livewire 3 components should use the App\Livewire namespace and lifecycle hooks like mount() and updatedFoo()

Files:

  • app/Livewire/Project/Application/General.php
**/*.php

📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)

**/*.php: Follow PSR-12 coding standards for all PHP code
Format PHP code with Laravel Pint configuration
Run static analysis with PHPStan to ensure type safety in PHP code
Document complex methods with PHPDoc blocks including parameters, return types, and thrown exceptions

**/*.php: Follow PSR-12 PHP coding standards across the codebase
Prefer eager loading and query optimization to prevent N+1 issues in database interactions
Use Laravel best practices for structure, services, and policies

**/*.php: Always use curly braces for control structures in PHP, even for single-line bodies
Use PHP 8 constructor property promotion in __construct() and avoid empty constructors
Always declare explicit return types for functions and methods; add appropriate parameter type hints
Prefer PHPDoc blocks over inline comments; only add inline code comments for very complex logic
When documenting arrays, add useful array shape types in PHPDoc where appropriate
Enum case names should be TitleCase (e.g., FavoritePerson, Monthly)

Files:

  • app/Livewire/Project/Application/General.php
app/**/*.php

📄 CodeRabbit inference engine (.cursor/rules/development-workflow.mdc)

Use database transactions to group related write operations for consistency in services/controllers/jobs

Files:

  • app/Livewire/Project/Application/General.php
app/Livewire/**

📄 CodeRabbit inference engine (.cursor/rules/project-overview.mdc)

Implement frontend components as Livewire classes under app/Livewire

Files:

  • app/Livewire/Project/Application/General.php
{app/Http/Controllers/**/*.php,app/Livewire/**/*.php}

📄 CodeRabbit inference engine (.cursor/rules/README.mdc)

Authorize sensitive actions with policies (e.g., $this->authorize('deploy', $model)) before invoking services

Files:

  • app/Livewire/Project/Application/General.php
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/frontend-patterns.mdc:0-0
Timestamp: 2025-08-27T15:03:30.794Z
Learning: Applies to app/Livewire/**/*.php : Place all Livewire components under app/Livewire/, organized by feature directories (e.g., Server/, Project/, Settings/, Team/, Profile/, Security/)
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/technology-stack.mdc:0-0
Timestamp: 2025-08-27T15:06:41.387Z
Learning: Applies to app/Livewire/**/*.php : Place Livewire components under app/Livewire/ (e.g., Dashboard.php, ActivityMonitor.php, MonacoEditor.php)
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/project-overview.mdc:0-0
Timestamp: 2025-08-27T15:04:22.911Z
Learning: Applies to app/Livewire/** : Implement frontend components as Livewire classes under app/Livewire
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/laravel-boost.mdc:0-0
Timestamp: 2025-10-15T09:16:25.875Z
Learning: Applies to app/Livewire/**/*.php : Livewire 3 components should use the App\Livewire namespace and lifecycle hooks like mount() and updatedFoo()
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/application-architecture.mdc:0-0
Timestamp: 2025-08-27T14:59:11.004Z
Learning: Applies to app/Livewire/**/*.php : Define Livewire components in app/Livewire and keep HTTP/UI concerns there
📚 Learning: 2025-08-27T15:03:30.794Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/frontend-patterns.mdc:0-0
Timestamp: 2025-08-27T15:03:30.794Z
Learning: Applies to app/Livewire/**/*.php : Declare protected $rules and validate with $this->validate() in Livewire form actions

Applied to files:

  • app/Livewire/Project/Application/General.php
📚 Learning: 2025-08-27T15:02:37.804Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/form-components.mdc:0-0
Timestamp: 2025-08-27T15:02:37.804Z
Learning: Applies to app/View/Components/Forms/{Input,Select,Textarea,Checkbox,Button}.php : Form component classes must define public properties: ?string $canGate = null, mixed $canResource = null, bool $autoDisable = true

Applied to files:

  • app/Livewire/Project/Application/General.php
📚 Learning: 2025-08-27T15:01:10.040Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/deployment-architecture.mdc:0-0
Timestamp: 2025-08-27T15:01:10.040Z
Learning: Applies to app/Services/ConfigurationGenerator.php : Generate deployment configuration via app/Services/ConfigurationGenerator.php rather than hardcoding in actions

Applied to files:

  • app/Livewire/Project/Application/General.php
📚 Learning: 2025-08-27T15:01:10.040Z
Learnt from: CR
Repo: coollabsio/coolify PR: 0
File: .cursor/rules/deployment-architecture.mdc:0-0
Timestamp: 2025-08-27T15:01:10.040Z
Learning: Applies to app/Services/DockerImageParser.php : Use app/Services/DockerImageParser.php to parse and validate Docker image references

Applied to files:

  • app/Livewire/Project/Application/General.php
🧬 Code graph analysis (1)
app/Livewire/Project/Application/General.php (6)
app/Livewire/Project/Database/Clickhouse/General.php (2)
  • General (15-219)
  • syncData (106-138)
app/Models/Application.php (9)
  • portsMappings (601-606)
  • customNetworkAliases (217-265)
  • dockerfileLocation (560-575)
  • dockerComposeLocation (577-592)
  • customNginxConfiguration (726-732)
  • settings (438-441)
  • parseContainerLabels (1578-1596)
  • type (453-456)
  • loadComposeFile (1459-1576)
app/Livewire/Project/Service/FileStorage.php (1)
  • syncData (69-84)
app/Livewire/Project/Application/Source.php (1)
  • syncData (65-85)
bootstrap/helpers/shared.php (1)
  • defaultNginxConfiguration (2976-3027)
bootstrap/helpers/docker.php (1)
  • generateLabelsApplication (595-737)
⏰ 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 (4)
app/Livewire/Project/Application/General.php (4)

372-477: LGTM! syncData implementation follows the expected pattern.

The two-way synchronization logic correctly handles the toModel flag, validates before persisting, and includes proper null handling for customLabels at lines 404-406. The separation of concerns between Application properties and ApplicationSetting properties is clear.


479-522: LGTM! instantSave correctly implements the syncData pattern.

The method properly captures old values before syncing (lines 484-488), calls syncData(toModel: true), performs conditional logic based on changes, and refreshes from the model with syncData() at line 502. This resolves the SPA toggle regression mentioned in past reviews.


609-614: Verify buildPack property is current when lifecycle hook fires.

The updatedBaseDirectory hook checks $this->buildPack at line 611 without explicitly syncing from the model first. While this is likely safe because mount() syncs at line 369 and Livewire processes updates sequentially, confirm that buildPack cannot be stale if multiple properties are updated in the same request cycle.


524-568: LGTM! Helper methods correctly use syncData pattern.

Methods like loadComposeFile (line 545), getWildcardDomain (lines 690-693), generateNginxConfiguration (lines 708-711), and resetDefaultLabels (line 728) properly call syncData() to refresh component properties after modifying the model, maintaining consistency between the component and model state.

Also applies to: 681-736

@andrasbacsai andrasbacsai merged commit d7e3a8a into v4.x Nov 4, 2025
6 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Nov 4, 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.

2 participants