Add centralized stop grace period resolution for application settings and use it across manual stops, preview stops, and deployments. Validate the Livewire advanced setting against shared min/max constants and cover persistence, fillable creation, and fallback behavior with tests.
Use random_bytes before hex and base64 encoding so generated env values
match the expected decoded byte lengths. Add Pest coverage for HEX and
REALBASE64 magic variables.
Replace 8× repeated per-type if-blocks in `queryDatabaseByUuidWithinTeam`
and `queryResourcesByUuid` with a single loop over the new
`STANDALONE_DATABASE_MODELS` constant.
Add unit tests to guard the registry against drift (keys mirror
`DATABASE_TYPES`, every entry is a valid Eloquent model with `team()`),
and feature tests covering team-ownership, wrong-team, and unknown-UUID
cases for `queryDatabaseByUuidWithinTeam`.
Introduce a dedicated `audit` log channel (daily rotation, configurable retention via
LOG_AUDIT_DAYS) and a small `auditLog()` / `auditLogWebhookFailure()` helper used to
record state-changing API operations and webhook events.
Instrumented:
- API mutation endpoints (create / update / delete / start / stop / restart) across
applications, services, databases (incl. backups, env vars, storage), servers,
projects + environments, scheduled tasks, private keys, GitHub apps, cloud provider
tokens, Hetzner server provisioning, instance enable/disable.
- Webhook signature verification outcomes for GitHub, GitLab, Bitbucket, Gitea and
Stripe, plus the Sentinel push endpoint.
- Authentication and authorization outcomes via the global exception handler and
the `ApiAbility` middleware (unauthenticated, ability-denied, policy-denied).
The helper is wrapped in try/catch so logging failures never affect the request
path. Successful operations log at `info`; suspicious/denied requests log at
`warning`. Operators wanting a failures-only feed can set `LOG_AUDIT_LEVEL=warning`.
Includes a feature test suite covering the helper, the webhook providers and the
new auth/authorization log paths.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds stop_grace_period to application settings (seconds, 1-3600, default 30).
Used in place of the hardcoded docker stop -t 30 in the four places that
stop application containers: rolling update shutdown, manual stop, stop on
another server, and preview deployment stop.
Non-positive values fall back to the default via ($val > 0) ? $val : default,
with tests covering 0 and -10 so the cast does not blow up if a bad value
ever lands in the db.
Picks up Jack Coy's work from #7125 which went dormant. His commits are
squashed here with credit below.
Co-authored-by: Jack Coy <jackman3000@gmail.com>
Validate new init-script filenames against path traversal and shell
metacharacters via a new validateFilenameSafe() helper, and harden the
write/delete paths with basename() + escapeshellarg() so legacy rows
still deploy and can be cleaned up without regressions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Use find_destination_for_current_team helper across resource creation
flows and the destination controller. Pass full destination objects to
database creation helpers instead of UUIDs so team relationships are
resolved consistently before the resource is created or linked.
Add feature tests covering destination, backup storage, and resource
proof lookups across teams.
Replace all uses of `forceFill`, `forceCreate`, and `forceFill` with their
non-force equivalents across models, actions, controllers, and Livewire
components. Add explicit `$fillable` arrays to all affected Eloquent models
to enforce mass assignment protection.
Add ModelFillableCreationTest and ModelFillableRegressionTest to verify that
model creation respects fillable constraints and prevent regressions.
Handle database status updates more reliably by listening for `ServiceChecked`
and using explicit `refresh()` handlers in Livewire database components.
Also switch guarded clone/create paths to `forceFill`/`forceCreate` in helper
flows to avoid missing persisted attributes during app/service cloning.
Update log/terminal font stacks to Geist (with bundled variable fonts) and add
coverage for SSL status refresh, persistent volume UUID cloning, and log font
styling.
Add end-to-end support for `docker_registry_image_tag` in preview and deployment queue flows.
- Extend deploy API to accept `pull_request_id` alias and `docker_tag` for preview deploys
- Persist preview-specific Docker tags on `application_previews` and `application_deployment_queues`
- Pass tag through `queue_application_deployment()` and de-duplicate queued jobs by tag
- Update deployment job logic to resolve and use preview Docker tags for dockerimage build packs
- Update Livewire previews UI/state to manage per-preview tags and manual preview/tag inputs
- Add migration for new tag columns and model fillable/casts updates
- Add feature and unit tests covering API behavior and tag resolution
Replace create() with forceCreate() across internal model creation operations to bypass mass assignment protection. This is appropriate for internal code that constructs complete model state without user input.
Add InternalModelCreationMassAssignmentTest to ensure internal model creation behavior is properly tested. Optimize imports by using shortened Livewire attribute references and removing unused imports.
Ensure that the uuid field is preserved during clone operations for persistent
volumes across all clone methods (CloneMe, ResourceOperations, and the clone_application
helper). This prevents UUID conflicts and ensures cloned volumes receive new unique
identifiers as intended.
Adds test coverage validating that cloned persistent volumes receive new UUIDs
distinct from the original volumes.
Replace $guarded = [] with explicit $fillable whitelists across all
models. Update controllers to use request->only($allowedFields) when
assigning request data. Switch Livewire components to forceFill() for
explicit mass assignment. Add integration tests for mass assignment
protection.
Add strict validation for Docker network names using a regex pattern
that matches Docker's naming rules (alphanumeric start, followed by
alphanumeric, dots, hyphens, underscores).
Changes:
- Add DOCKER_NETWORK_PATTERN to ValidationPatterns with helper methods
- Validate network field in Destination creation and update Livewire components
- Add setNetworkAttribute mutator on StandaloneDocker and SwarmDocker models
- Apply escapeshellarg() to all network field usages in shell commands across
ApplicationDeploymentJob, DatabaseBackupJob, StartService, Init command,
proxy helpers, and Destination/Show
- Add comprehensive tests for pattern validation and model mutator
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add shellSafeCommandRules() validation to install_command, build_command,
and start_command fields in both the Livewire UI and REST API layers.
These fields previously accepted arbitrary strings without validation,
unlike other shell-adjacent fields which already used this pattern.
Also adds comprehensive tests for rejection of dangerous input and
acceptance of legitimate build commands.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Delegate host validation to parent class instead of custom implementation
- Update base_url() helper to use config('app.url') instead of url('/')
- Add test for APP_URL fallback when no FQDN or public IPs configured
- Remove dedicated TrustHostsMiddlewareTest (logic now tested via integration tests)
- Add support for bracketed IPv6 addresses when FQDN is not configured
- Harden password reset URL generation against X-Forwarded-Host header poisoning
- Add test coverage for IPv6-only configurations with malicious headers
- Update imports and clean up exception syntax in shared helpers
- Inline PrepareCoolifyTask and CoolifyTaskArgs into remote_process(),
removing two single-consumer abstraction layers
- Add #[Locked] attribute to ActivityMonitor $activityId property
- Add team ownership verification in ActivityMonitor.hydrateActivity()
with server_uuid fallback and fail-closed default
- Store team_id in activity properties for proper scoping
- Update CLAUDE.md to remove stale reference
- Add comprehensive tests for activity monitor authorization
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add validateDatabasesBackupInput() helper that properly parses all
database backup formats including MongoDB's "db:col1,col2|db2:col3"
and validates each component individually.
- Validate and escape collection names in DatabaseBackupJob
- Replace comma-only split in BackupEdit with format-aware validation
- Add input validation in API create_backup and update_backup endpoints
- Add unit tests for collection name and multi-format validation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Do not replace self-referencing environment variables (e.g., DATABASE_URL: ${DATABASE_URL})
with saved DB values in the compose environment section. Keeping the reference intact allows
Docker Compose to resolve from .env at deploy time, preventing stale values from overriding
user updates that haven't been re-parsed.
Fixes#9136
- Normalize hostnames to lowercase for RFC 1123 compliance while accepting uppercase input
- Expand NAME_PATTERN to allow parentheses, hash, comma, colon, and plus characters
- Add fallback to random name generation when application name doesn't meet minimum requirements
- Add comprehensive test coverage for validation patterns and edge cases
Add escapeShellValue() helper function to safely escape shell values by wrapping
them in single quotes and escaping embedded quotes. Use this function throughout
the nixpacks command building to prevent shell injection vulnerabilities when
passing user-provided build commands, start commands, and environment variables.
This fixes unsafe string concatenation that could allow command injection when
user input contains special shell characters like &&, |, ;, etc.
- Add storage endpoints (list, create, update, delete) to DatabasesController
- Add storage endpoints (list, create, update, delete) to ServicesController
- Add UUID field and migration for local_persistent_volumes table
- Update LocalPersistentVolume model to extend BaseModel
- Support UUID-based storage identification in ApplicationsController
- Update OpenAPI documentation with new storage endpoints and schemas
- Fix application name generation to extract repo name from full git path
- Add comprehensive tests for storage API operations
Extract the shouldRunNow() method from ScheduledJobManager and ServerManagerJob into
a reusable shouldRunCronNow() helper function. This centralizes cron scheduling logic
and enables consistent deduplication behavior across all scheduled job types.
- Create shouldRunCronNow() helper in bootstrap/helpers/shared.php with timezone
and dedup support
- Refactor ScheduledJobManager and ServerManagerJob to use the shared helper
- Add ScheduledJobDiagnostics command for inspecting cache state and scheduling
decisions across all scheduled jobs
- Simplify shouldRunNow tests to directly test the helper function
- Add DockerCleanupJob test for error handling and execution tracking
- Increase scheduled log retention from 1 to 7 days
Add `is_preview_suffix_enabled` flag to `local_file_volumes` and
`local_persistent_volumes` tables, allowing per-volume control over
whether a `-pr-N` suffix is appended during preview deployments.
Defaults to `true` to preserve existing behavior. Users can disable
it for volumes containing shared config or repository scripts that
should not be isolated per PR.
Bind mount volumes reference files at the repository's original path and
should not receive the -pr-N suffix. Only named Docker volumes require
the suffix for isolation between preview deployments.
Adds PreviewDeploymentBindMountTest to verify the correct behavior.
Fixes#7802
Extract shared variable resolution logic into a reusable helper function
`resolveSharedEnvironmentVariables()` and apply it in applicationParser and
serviceParser to ensure patterns like {{environment.VAR}}, {{project.VAR}},
and {{team.VAR}} are properly resolved in the compose environment section.
Without this, unresolved {{...}} strings would take precedence over resolved
values from the .env file (env_file:) in docker-compose configurations.