Commit graph

1031 commits

Author SHA1 Message Date
Andras Bacsai
65c0c92c02 fix(destinations): handle empty and server-scoped destinations
Build the global destinations list from actual destination records so empty
servers do not render duplicate empty states. Allow creating Docker destinations
for a selected team server outside the global usable list, authorize swarm
creation correctly, and store discovered swarm network names from the selected
network. Add feature coverage for empty states, selected-server mounting, and
swarm destination creation.
2026-05-19 12:50:08 +02:00
Andras Bacsai
fde500a347 fix(templates): require Docmost mail driver
Require MAIL_DRIVER to be set before Docmost starts and add a unit test to keep the compose template and generated service templates in sync.
2026-05-15 13:36:02 +02:00
Julien Bouquillon
89d7672253 feat(api): add is_preview_deployments_enabled on applications 2026-05-13 13:09:18 +02:00
Andras Bacsai
d1126c02a9 fix(deployments): filter generated compose service env vars
Exclude generated Docker Compose SERVICE_FQDN, SERVICE_URL, and SERVICE_NAME variables from runtime, build-time, and build arg environments so stale stored values cannot override generated service names for preview deployments.
2026-05-13 11:59:45 +02:00
Andras Bacsai
a54e70b4e0 fix(deployments): skip registry image tag for previews
Only push the configured Docker registry image tag for production deployments, and cover preview and missing-tag cases with unit tests.
2026-05-13 11:49:15 +02:00
Andras Bacsai
fb13a6cdc0 fix(api): expose cloud tokens with sensitive read access
Show cloud provider token values only when the API request has sensitive
read permission, and cover read, read:sensitive, and root token behavior.
2026-05-13 11:29:48 +02:00
Andras Bacsai
6ab88c46b2 Merge remote-tracking branch 'origin/next' into audit-policies 2026-05-13 11:15:29 +02:00
Andras Bacsai
4ff3e4b2be
feat(deployments): track application configuration diffs (#10183) 2026-05-13 10:49:53 +02:00
Andras Bacsai
1522c510cf fix(api-tokens): mark expiration warning after notification
Ensure failed token expiration warning notifications do not persist the warning marker, allowing the job to retry later.
2026-05-13 10:28:32 +02:00
Andras Bacsai
df4d9f8069 fix(applications): use preview environment variable query
Call the preview environment variable relationship as a query when building the legacy configuration hash, and cover preview deployments with a regression test.
2026-05-13 10:28:18 +02:00
Andras Bacsai
3911a0305c fix(api-tokens): persist expiration warning state
Track when expiration warnings are sent on personal access tokens so repeated job runs or cache flushes do not send duplicate notifications.
2026-05-13 10:11:40 +02:00
Andras Bacsai
0ecd488d6a fix(applications): refresh pending configuration changes
Dispatch configuration change events after saving application source and advanced settings, and refresh the configuration checker before showing redeploy diffs.
2026-05-13 10:04:17 +02:00
Andras Bacsai
f8849aba73 feat(deployments): track application configuration diffs
Store deployment configuration snapshots on application deployment queues and compare them against the current application state. Surface grouped pending changes in the configuration checker and use build-impact diffs to decide when an existing image can skip the build step.
2026-05-13 09:58:58 +02:00
Andras Bacsai
d8972e97c9 fix(previews): clean up closed PR previews after update failures
Catch and report failures while updating closed pull request status so preview deployment cleanup still runs for closed GitHub pull request webhooks.

Add coverage for cleanup continuing when GitHub comment cleanup fails.
2026-05-13 09:31:28 +02:00
Andras Bacsai
63c2d31ca0 feat(applications): add configurable stop grace period
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.
2026-05-11 23:43:53 +02:00
Andras Bacsai
d1220895d9 Merge remote-tracking branch 'origin/next' into feat/configurable-stop-grace-period 2026-05-11 23:20:31 +02:00
Andras Bacsai
6f3bb47682
fix(applications): decode custom nginx API payloads (#10067) 2026-05-11 22:24:55 +02:00
Andras Bacsai
a42613168d fix(applications): store custom nginx config from API correctly
Decode base64 custom_nginx_configuration before model assignment so it is not double-encoded, and allow null values when clearing the setting. Add API coverage for create, update, invalid input, and clearing behavior.
2026-05-11 22:22:01 +02:00
Andras Bacsai
9bb40f3ccb fix(deployment): avoid shared preview tags for HEAD commits
Use the deployment UUID when preview deployments are built from HEAD so each deployment gets distinct production and build image tags.
2026-05-11 22:11:08 +02:00
Andras Bacsai
2253c40e01 fix(deployment): include commit in preview image tags
Generate pull request preview image tags with both the PR id and commit
so different commits on the same PR do not reuse the same image tag. Sanitize
and truncate generated tags to stay within Docker tag limits.
2026-05-11 22:05:07 +02:00
Andras Bacsai
81a3bb0f07 fix(api): hide sensitive fields by default
Add model-level hidden fields for secrets, tokens, keys, notification
credentials, deployment logs, and environment values. Allow explicit
read:sensitive API access to reveal gated private keys and deployment logs,
and cover the behavior with feature and unit tests.
2026-05-11 21:18:07 +02:00
Andras Bacsai
c175d3d282 Merge remote-tracking branch 'origin/next' into audit-policies 2026-05-11 21:13:57 +02:00
Andras Bacsai
b29bdce73a Merge remote-tracking branch 'origin/next' into api-sensitive-data-scrubber 2026-05-11 17:34:48 +02:00
Andras Bacsai
ab1958d741 fix(railpack): fail fast when buildx is unavailable
Require Docker buildx before Railpack builds, normalize environment
variable keys before validation, and align private deploy key API docs with
the supported dockerfile build pack.
2026-05-11 17:31:29 +02:00
Andras Bacsai
0395db30f0 fix(railpack): align example ports and smoke checks
Update Railpack seed examples to use the expected Flask start command and Go/Rust exposed ports. Adjust smoke coverage to run Symfony by default and accept reachable 4xx responses, and extend seeder tests for per-example branch and port assertions.
2026-05-11 17:13:55 +02:00
Andras Bacsai
0f904d792b Merge remote-tracking branch 'origin/next' into feat/railpack 2026-05-11 17:03:25 +02:00
Andras Bacsai
ff149b8daa fix(stripe): ignore missing subscriptions in webhook jobs
Avoid failing Stripe webhook processing when local subscriptions are missing, and cover ignored invoice/payment/subscription events with feature tests.
2026-05-11 16:56:00 +02:00
Andras Bacsai
db7d0f0bfb Merge remote-tracking branch 'origin/next' into feat/railpack 2026-05-11 16:26:50 +02:00
Andras Bacsai
d96e253230 fix(ui): align deployment indicator with collapsed sidebar
Move the deployments indicator inside the app layout state scope so it can react to the sidebar collapsed state, and add a layout test covering the responsive positioning.
2026-05-11 16:25:15 +02:00
Andras Bacsai
b5ff124446 fix(env): validate Docker-compatible variable keys
Add shared environment variable key validation and normalization for Livewire forms and models, allowing Docker-compatible keys while rejecting invalid entries such as keys containing equals signs. Also quote Railpack build environment and secret arguments safely.
2026-05-11 15:43:09 +02:00
Andras Bacsai
d5946dcfca fix(railpack): include scoped env vars in builds
Build Railpack variables from generic build-time vars plus Railpack-specific vars, filter unrelated buildpack control vars, and ensure curl/wget deploy apt packages are present. Add coverage for standard and preview deployments.
2026-05-11 13:29:21 +02:00
Andras Bacsai
6ee75cfa65 fix(api): remove deprecated docker compose application endpoint
Drop the unstable applications/dockercompose route and controller path now that
service creation is handled by POST /api/v1/services. Add coverage to ensure the
deprecated endpoint stays unregistered while the services endpoint remains
available.
2026-05-11 13:20:05 +02:00
Andras Bacsai
12aba41d9a fix(api): gate service server secrets by sensitive scope
Only eager load nested server settings for service responses when the API token has read:sensitive, preventing read-only tokens from exposing sentinel fields while preserving sensitive access.
2026-05-11 11:53:22 +02:00
Andras Bacsai
c97f916052 fix(api): hide application compose PR fields
Add compose PR fields to the Application hidden attributes and allow database list queries to eager load nested server settings when sensitive access is permitted.
2026-05-11 11:46:05 +02:00
Andras Bacsai
ffa494d391 Merge remote-tracking branch 'origin/next' into api-sensitive-data-scrubber 2026-05-11 11:36:24 +02:00
Andras Bacsai
9f380b8495 Merge remote-tracking branch 'origin/next' into feat/railpack 2026-05-11 10:58:13 +02:00
Andras Bacsai
c6ac52dc38 fix(env): generate encoded secrets from raw random bytes
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.
2026-05-09 14:49:39 +02:00
Andras Bacsai
fe934dd139 Merge remote-tracking branch 'origin/next' into feat/railpack 2026-05-06 14:33:22 +02:00
Andras Bacsai
c553b6aef9 Merge remote-tracking branch 'origin/next' into api-sensitive-data-scrubber 2026-05-06 14:33:19 +02:00
Andras Bacsai
29d41ba041 Merge remote-tracking branch 'origin/next' into 9916-investigate-undefined-relationship 2026-05-06 14:32:16 +02:00
Andras Bacsai
0888198a81 Merge remote-tracking branch 'origin/next' into api-sensitive-data-scrubber 2026-05-05 22:09:34 +02:00
Andras Bacsai
45f65481e6 fix(mcp): change enable/disable endpoints from GET to POST and fix service/app listing
- `/mcp/enable` and `/mcp/disable` now use POST (state-mutating ops)
- `ListServices` queries DB directly instead of loading all projects into memory
- `ListApplications` validates tag arg rejects empty string (not just falsy)
2026-05-05 22:07:58 +02:00
Andras Bacsai
22a2c05a1d test(railpack): add API, Livewire UI tests and e2e smoke script
Add feature tests covering railpack build pack via REST API and
Livewire UI components, plus a bash smoke test that deploys seeded
railpack-* example apps against the local dev stack and verifies
COOLIFY_*, SOURCE_COMMIT, and RAILPACK_* env vars land correctly.
2026-05-05 15:32:43 +02:00
Andras Bacsai
1849b5903e refactor(scheduled-task): simplify server() with nullsafe operators and add return type
Replace nested null checks with nullsafe operator chains, add ?Server
return type, drop unreachable database branch, and cover all paths with
feature tests.
2026-05-04 12:26:15 +02:00
Andras Bacsai
b6ca6b1b20 feat(railpack): expose COOLIFY_* vars at build time and generalize buildpack control flag
Mirrors Nixpacks behavior: inject COOLIFY_* and SOURCE_COMMIT into
railpack build variables so apps (e.g. SPAs baking public URLs) can
read them via /run/secrets/<KEY>.

Rename is_nixpacks → is_buildpack_control to cover both NIXPACKS_ and
RAILPACK_ prefixed keys. Update the env variable view and appends list
accordingly.

Promote generate_coolify_env_variables to protected for testability.
2026-04-30 18:31:41 +02:00
Andras Bacsai
ea0ade442b Merge remote-tracking branch 'origin/next' into api-sensitive-data-scrubber 2026-04-30 16:45:34 +02:00
Andras Bacsai
ace643d3d8 fix(railpack): query buildtime env vars directly instead of via computed attribute
Replace `railpack_environment_variables_collection()` helper (which returned
pre-filtered Eloquent attribute collections) with inline queries on
`environment_variables()` / `environment_variables_preview()` filtered by
`is_buildtime`. This ensures Railpack build variables are sourced from the
same query path as the rest of the deployment pipeline and avoids relying on
a now-removed accessor that silently included all railpack vars regardless of
build context.
2026-04-30 16:38:58 +02:00
Andras Bacsai
ec71d33f5e fix(railpack): pin frontend image version via config constant
Remove RAILPACK_FRONTEND_IMAGE env var from helper Dockerfile and resolve
the image ref at runtime using a new `railpack_version` constant in config.
Eliminates Docker build-time env interpolation for BUILDKIT_SYNTAX arg.
2026-04-30 16:27:08 +02:00
Andras Bacsai
a51f114a70 fix(standalone-docker): include keydb, dragonfly, clickhouse in databases()
Add missing DB types to StandaloneDocker::databases() concat chain and
cover all 8 standalone database types with feature tests.
2026-04-30 15:01:48 +02:00
Andras Bacsai
79174b749d refactor(helpers): extract STANDALONE_DATABASE_MODELS registry, add tests
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`.
2026-04-30 14:48:48 +02:00
Andras Bacsai
0f830b31f3 Merge remote-tracking branch 'origin/next' into mcp-server-instance-toggle 2026-04-30 14:48:35 +02:00
Andras Bacsai
8dc79f4ed6 fix(api): expose nested server secrets for privileged tokens
Add `exposeNestedServerSecrets()` to Applications, Databases, and
Services controllers so that `read:sensitive`/`root` tokens see
sentinel and logdrain fields on eager-loaded Server + ServerSetting
relations.

ServicesController handles both single models and Eloquent Collections
(listing endpoint passes a Collection per project).

Tests tightened to use JSON-key assertions (`"field":`) to avoid false
positives from field names appearing in values.
2026-04-30 11:49:15 +02:00
Andras Bacsai
8e91d627a3 Merge remote-tracking branch 'origin/next' into feat/railpack 2026-04-30 11:47:06 +02:00
Andras Bacsai
f9b3f89757 Merge remote-tracking branch 'origin/next' into suppress-horizon-job-failures 2026-04-30 11:42:52 +02:00
Andras Bacsai
e828058755 Merge remote-tracking branch 'origin/next' into api-sensitive-data-scrubber 2026-04-30 11:30:50 +02:00
Andras Bacsai
d057ce5172 Merge remote-tracking branch 'origin/next' into mcp-server-instance-toggle 2026-04-30 11:30:45 +02:00
Andras Bacsai
8b7dbbafb2 fix(api): hide sensitive fields by default, expose via makeVisible for privileged tokens
Models now declare $hidden for passwords, tokens, db URLs, and compose
fields. API controllers flip from makeHidden-on-deny to makeVisible-on-
allow (can_read_sensitive=true), fixing fields that were never hidden.
Also adds missing fields (mysql/mariadb passwords, logdrain keys, etc.)
to privileged disclosure lists.

Tests added: Feature/Security/ApiSensitiveFieldsTest and
Unit/Models/SensitiveFieldsHiddenTest cover all affected models and
controllers.
2026-04-30 11:28:06 +02:00
Andras Bacsai
4575106f53 feat(sentinel): embed server UUID in encrypted sentinel token
Replace random string with encrypted JSON payload containing
server_uuid, binding token to its server for validation.
Remove double-encrypt test no longer relevant to new token format.
2026-04-30 08:21:30 +02:00
Andras Bacsai
00d6e83e7f fix(sentinel): auto-regenerate invalid or undecryptable tokens
Replace hard validation error with self-healing token logic. Tokens that
are null, empty, or fail decryption are now regenerated automatically
rather than crashing sentinel startup or metrics reads.

Token format changed from encrypted JSON payload to a plain 64-char
random string (Str::random), eliminating double-encryption issues and
simplifying the validation regex to cover the new character set.

New `ensureValidSentinelToken()` method on ServerSetting centralises
the get-or-regenerate contract; both StartSentinel and HasMetrics now
delegate to it. HasMetrics logs a warning when regeneration occurs so
operators know a sentinel container restart is required.

`isValidSentinelToken()` now accepts `?string` (null → false).

Adds feature tests covering: null/empty/undecryptable stored values,
idempotent return of valid tokens, RuntimeException only when
regeneration itself produces an invalid token, no double-encryption of
newly generated tokens, and cast round-trip consistency.
2026-04-29 16:44:12 +02:00
Andras Bacsai
fc3ce85f88 feat(horizon): suppress failed job entries for deployment/timeout errors on cloud
On cloud, DeploymentException and TimeoutExceededException are expected
failure modes that pollute the Horizon failed jobs UI. Listen to JobFailed
events and scrub the entry via JobRepository::deleteFailed so operators
are not alerted for noise failures. Self-hosted instances are unaffected.
2026-04-29 15:40:01 +02:00
Andras Bacsai
b8e311622a Merge remote-tracking branch 'origin/next' into feat/railpack 2026-04-29 15:22:47 +02:00
Andras Bacsai
6d1d699595 fix(deployments): resolve commit from app git_commit_sha when not explicitly set
Change `commit` param from `string 'HEAD'` default to `?string null`, then
resolve priority: explicit param > app `git_commit_sha` > `'HEAD'` fallback.

Add feature tests covering all four resolution paths.
2026-04-29 10:59:32 +02:00
Andras Bacsai
7ab16ad7b5 feat(mcp): add MCP server with read-only tools for Coolify resources
Add Model Context Protocol server exposing Coolify infrastructure data
to AI assistants. Includes tools for listing/fetching servers, projects,
applications, databases, and services, scoped to authenticated team tokens.

- Add CoolifyServer with 10 read-only tools (list/get for all resource types)
- Add BuildsResponse and ResolvesTeam traits for shared tool logic
- Add EnsureMcpEnabled middleware guarding /mcp routes
- Add enable/disable MCP API endpoints (root-only)
- Add is_mcp_server_enabled toggle in instance settings and advanced UI
- Add migration for is_mcp_server_enabled column
- Add feature tests for MCP endpoints and toggle API
- Scrub sensitive keys (passwords, tokens, raw IDs) from all responses
2026-04-29 10:30:43 +02:00
Andras Bacsai
46180dbbf9 feat(webhook): skip deployment on [skip ci]/[skip cd] commit markers
Add DetectsSkipDeployCommits trait with two strategies: shouldSkipDeploy
(all commits must contain the marker) for push events, and
shouldSkipDeployAny (any single marker triggers skip) for PR/MR titles
and latest-commit signals.

Apply trait to Bitbucket, Gitea, GitHub, GitLab webhook controllers and
ProcessGithubPullRequestWebhook job. PRs pass pullRequestTitle through
to the job constructor for evaluation.
2026-04-29 09:12:24 +02:00
Andras Bacsai
9717d9ff5a Merge remote-tracking branch 'origin/next' into feat/railpack 2026-04-29 08:56:23 +02:00
Andras Bacsai
eaaf258f25 fix(service): block UI editing of file volumes exceeding 5 MiB
Large host files mounted via Docker volumes caused the storages page to
become unusable — full file content was stored in the encrypted mediumText
column and serialised into the Livewire payload, crashing the browser.

- Add MAX_CONTENT_SIZE (5 MiB), BINARY_PLACEHOLDER, and TOO_LARGE_PLACEHOLDER
  constants to LocalFileVolume
- Check remote file size via stat/wc before cat in loadStorageOnServer and
  saveStorageOnServer; store placeholder instead of content when limit exceeded
- Expose is_too_large computed attribute (appended for Livewire serialisation)
- Guard submit, instantSave, and syncData in FileStorage Livewire component
- Truncate oversized content in Storage::refreshStorages to prevent payload bloat
- Show distinct warning banner in file-storage blade; mark textarea readonly and
  hide Save/Convert buttons for too-large files
- Add unit tests covering constants, computed flags, and toArray serialisation

Fixes #4701
2026-04-28 22:36:56 +02:00
Andras Bacsai
19994a0a13 test(api): add feature tests for server connection_timeout API
Tests cover PATCH update success, out-of-range, above-max, and
non-integer validation for the connection_timeout field.
2026-04-28 22:20:15 +02:00
Andras Bacsai
6293b14586 feat(server): add configurable SSH connection timeout per server
Add `connection_timeout` field to server settings, allowing per-server
override of the global SSH connection timeout constant.

- Migration adds `connection_timeout` integer column (default 10s)
- `ServerSetting` model exposes and casts the new field
- `SshMultiplexingHelper::getConnectionTimeout()` resolves per-server
  value with fallback to `constants.ssh.connection_timeout`
- All SSH/SCP command builders use the new resolver instead of the
  global config directly
- Livewire `Show` component binds `connectionTimeout` with validation
  (1–300 seconds) and syncs to/from the model
- UI input added to server settings form with helper text
- Feature tests cover default, persistence, resolver, and fallback
2026-04-28 15:39:36 +02:00
Jan Thiel
6637159d7b feat(hetzner): add support for enabling backups during server creation 2026-04-28 15:37:26 +02:00
Andras Bacsai
b8226be774 refactor(server): dispatch event for reachability notifications, drop retry loop
Move reachability notification triggering out of isReachableChanged into
a dedicated ServerReachabilityChanged event dispatched by
ServerConnectionCheckJob. Remove the blocking 3-attempt sleep loop from
isReachableChanged — unreachable_count threshold alone now gates the
Unreachable notification. Add feature and unit tests covering all
notification dispatch paths.
2026-04-28 15:28:22 +02:00
Andras Bacsai
a2096c6f68 feat(observability): add structured audit log channel for API and webhook events
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>
2026-04-28 14:50:37 +02:00
Andras Bacsai
b3339d1034 feat(railpack): add buildpack control var filtering and dev seeder
Extract NIXPACKS_/RAILPACK_ prefix filtering into a reusable
`scopeWithoutBuildpackControlVariables` query scope on EnvironmentVariable.
Apply scope consistently to runtime vars, runtime preview vars, and
buildtime var generation in ApplicationDeploymentJob.

Refactor `generate_railpack_env_variables` to return a Collection.
Add `RAILPACK_FRONTEND_IMAGE` constant and bake it into the
coolify-helper Dockerfile as a build arg.

Add DevelopmentRailpackExamplesSeeder (dev/local env only) for
seeding example Railpack apps, wired into DatabaseSeeder.

Add tests:
- ApplicationDeploymentControlVarFilteringTest: verifies control vars
  are excluded from runtime and buildtime envs
- DevelopmentRailpackExamplesSeederTest: verifies seeder behavior
- ApplicationDeploymentRailpackEnvParityTest: parity checks for env
  handling across build/runtime paths
2026-04-28 14:37:31 +02:00
Andras Bacsai
5cef7cc092 Merge remote-tracking branch 'origin/next' into feat/railpack 2026-04-28 14:36:54 +02:00
Andras Bacsai
cabcd8f699 fix(terminal): add idle timeout, reconnect replay, and scrollback preservation
- Kill PTY and notify client after 30 min of inactivity (IDLE_TIMEOUT_MS)
- Buffer client messages during async auth/IP fetch to prevent race-condition
  message loss on fast reconnects
- Replay last sent command after transient reconnect so PTY respawns without
  user interaction
- Preserve scrollback on disconnect/reconnect; write visible timestamp markers
  instead of wiping term state
- Handle idle-timeout sentinel on client with user-facing error message
2026-04-28 12:26:31 +02:00
Andras Bacsai
9408620d5f fix(terminal): add WS heartbeat and fix proxy idle disconnects
Proxies (Cloudflare, nginx) drop idle WebSocket connections before the
application notices, leaving clients typing into dead sockets.

- Add server-side ping/pong heartbeat (30s) in terminal-server.js;
  terminate unresponsive clients instead of letting connections go stale
- Move client keepAlive interval start to the connect event so it
  restarts correctly after reconnects
- Remove hidden-tab keepalive short-circuit — server pings now own
  liveness; suppressing client pings while hidden masked proxy drops
- Fix clearAllTimers to use clearTimeout for one-shot timers
- On visibility resume, probe with a 5s timeout instead of the default
  35s so half-open sockets are detected quickly
- Bump coolify-realtime to 1.0.14 across all compose files
2026-04-28 10:35:32 +02:00
Andras Bacsai
b4e139929e Merge remote-tracking branch 'origin/next' into fix/oauth-email-normalization 2026-04-27 14:56:16 +02:00
Hendrik Kleinwaechter
60d8aba323 feat: configurable stop grace period for applications
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>
2026-04-22 21:18:18 +02:00
Andras Bacsai
e1aac50b74
refactor(validation): tokenize shell-safe command pattern (#9684) 2026-04-20 22:04:36 +02:00
Andras Bacsai
817128c5af refactor(validation): tokenize shell-safe command pattern
Replace the flat character-class regex for SHELL_SAFE_COMMAND_PATTERN with
a token-aware alternation. The parser now recognizes explicit tokens
(`&&`, `||`, balanced single/double quotes, whitespace, and an unquoted
safe-char run) instead of a bag of characters, which lets us extend the
accepted grammar without loosening the guarantees.

New surface area, with tests:
- logical OR chaining (`make build || make clean`)
- shell globs and bang (`rm *.tmp`, `cp src/?.js dist/`, `! grep -q foo`)
- single-quoted arguments are now treated as balanced runs rather than
  rejected per-character

Preserved surface area:
- && chaining, balanced "..." and '...' quotes, the previous safe path /
  argument characters, and the existing error-path contract in
  ApplicationDeploymentJob::validateShellSafeCommand().

Also refreshes the user-facing validation messages in General.php so the
allow/deny list shown on failure matches the new grammar.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-20 22:00:41 +02:00
Andras Bacsai
f0e955bf45 refactor(database): escape postgres_user in SSL chown command
Apply escapeshellarg() to the Postgres username before interpolating it
into the chown command used to fix SSL certificate ownership, matching
the handling already in place for StartMysql. This keeps the sink-side
escaping consistent across database actions, independent of upstream
input validation.

Also adjusts an assertion in DatabaseSslCredentialEscapingTest to match
the actual double-escaped output of executeInDocker, and adds Postgres
regression cases for subshell and semicolon payloads.
2026-04-20 21:41:48 +02:00
Andras Bacsai
a05d4e3a4b fix(database): tighten Postgres init script filename handling
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>
2026-04-20 21:26:34 +02:00
Andras Bacsai
90ddbb3572 feat(security): support expiration on API tokens with warning notifications
Add optional expiration to personal API tokens. Users pick a duration
(1/7/30/60/90 days or Never) at creation time. Expired tokens are
rejected by Sanctum, pruned hourly by sanctum:prune-expired, and a
team notification fires ~24h before expiry so owners can rotate
before API calls start failing.

- ApiTokens Livewire component stores expires_at from expiresInDays
- Rework issued-tokens UI from card grid to table (matches other views)
- New ApiTokenExpirationWarningJob scheduled hourly (idempotent via RateLimiter)
- New ApiTokenExpiringNotification (email/discord/telegram/slack/pushover)
- api_token_expiring added to alwaysSendEvents so users cannot silence
  expiry warnings from the per-event notification toggle UI
- sanctum:prune-expired cadence moved from daily to hourly

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-20 14:28:38 +02:00
Andras Bacsai
40a9881ef2 fix(database): skip credential pattern validation for unchanged values
Pattern enforcement now conditional on field being dirty (changed vs
saved value). Prevents false validation failures when existing records
hold legacy credential formats that pre-date the stricter regex rules.
2026-04-20 13:58:44 +02:00
Andras Bacsai
03313e54cc fix(database): enforce credential format validation and sanitize init/SSL arguments
Add ValidationPatterns helpers for database identifiers and passwords,
apply them across database Livewire components and the API controller,
encode MongoDB init script values via json_encode, and pass the MySQL
user through escapeshellarg when generating SSL chown commands.
2026-04-20 13:58:36 +02:00
Andras Bacsai
2264a2ef76 docs(tests): replace advisory ID with descriptive comment in healthcheck injection test 2026-04-20 13:28:55 +02:00
Andras Bacsai
64753b4136 fix(database): prevent command injection in healthcheck via CMD exec-form
Replace CMD-SHELL string interpolation with CMD exec-form arrays in
healthcheck configs for PostgreSQL, Dragonfly, KeyDB, and ClickHouse.

CMD-SHELL passes the string to /bin/sh -c, allowing command injection
through user-controlled fields (username, password, dbname). CMD
exec-form bypasses the shell entirely — each value is a discrete argv
element.

Fixes GHSA-gvc4-f276-r88p.

Adds regression tests covering semicolon, pipe, backtick, $(),
background operator, redirect, newline, and null-byte injection vectors.
2026-04-20 13:17:15 +02:00
Andras Bacsai
bb0c3501ef refactor(cli): validate --date and escape shell args on logs:scheduled
Reject malformed --date values with a clear error before building any
shell command, and wrap every interpolated value (log paths, filter
expression, line count) in escapeshellarg() so filter options and date
values can no longer break out of the tail/grep pipeline.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-20 12:09:48 +02:00
Andras Bacsai
49b5472961 refactor(auth): upgrade email verification hash to sha256
Move the email-verification URL hash from sha1 to sha256 and verify it
directly in the controller using hash_equals, instead of going through
Laravel's EmailVerificationRequest (which only compares against sha1).
The signed URL still carries the authoritative HMAC; the hash upgrade
keeps the identity binding aligned with modern hashing guidance.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-20 12:09:48 +02:00
Andras Bacsai
9b37a1a7eb refactor(auth): drop implicit email verification on invitation link login
The invitation-link login path previously marked the account as
email-verified as a side effect of authenticating, without the user ever
proving control of the mailbox. Remove that branch so every account
goes through the standard signed-URL verification flow.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-20 12:09:48 +02:00
Andras Bacsai
e373037a2a test: remove GHSA advisory IDs from test descriptions and comments
Strip advisory identifiers (GHSA-*) from describe blocks, test
docblocks, and inline comments. Replace with plain descriptive
labels. Also clean up FQCNs to use imported class names and minor
style fixes (string concatenation spacing).
2026-04-20 12:07:42 +02:00
Andras Bacsai
ea639dab8f
refactor(api): return stable generic error messages for 5xx responses (#9669) 2026-04-20 11:53:20 +02:00
Andras Bacsai
fe8b3412d3
refactor(settings): harden dev_helper_version validation and escape build args (#9670) 2026-04-20 11:52:48 +02:00
Andras Bacsai
03a35faf2c
refactor(storage): tighten S3 endpoint URL validation (#9668) 2026-04-20 11:51:51 +02:00
Andras Bacsai
6a5fd40a5c refactor(policies): add uploadBackup ability and enforce it on backup upload endpoint
Introduce a dedicated `uploadBackup` ability on Application, Database,
Service, and ServiceDatabase policies (admin/owner only) and call
`$this->authorize('uploadBackup', $resource)` in `UploadController::upload`
so the backup-upload endpoint goes through the same policy layer as the
rest of the authorization refactor. Adds Pest coverage for each policy
variant plus HTTP-level checks.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-20 11:51:35 +02:00
Andras Bacsai
dc9322b11f refactor(settings): validate dev_helper_version and escape build args
Constrain dev_helper_version to Docker tag grammar
([A-Za-z0-9_][A-Za-z0-9_.-]{0,127}), re-validate before triggering the
helper image build, and interpolate the image reference via
escapeshellarg() when composing the docker build command.
2026-04-20 11:51:27 +02:00
Andras Bacsai
4d83688896 refactor(api): return generic error messages for upstream and storage failures
Replace exception text in 5xx JSON responses with stable, action-specific
messages so API consumers get a consistent payload regardless of which
underlying client (Guzzle, PDO, filesystem) raised the exception. The
previous responses concatenated the raw upstream error, which produced
inconsistent messages and unnecessary noise for clients trying to parse
errors programmatically.

Touched endpoints:
- GET /api/v1/hetzner/{locations,server-types,images,ssh-keys}
- POST /api/v1/servers/hetzner
- DELETE /api/v1/databases/{uuid}/backups/{uuid}
- DELETE /api/v1/databases/{uuid}/backups/{uuid}/executions/{uuid}
- /download/backup/{uuid}

The RateLimitException branch and AuthenticationException flow keep their
existing curated messages.

Adds Pest coverage for the four Hetzner GET endpoints to lock the response
shape on upstream failure.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-20 11:50:30 +02:00
Andras Bacsai
297e9c41e1 refactor(storage): tighten S3 endpoint URL validation
Reuse the existing SafeWebhookUrl rule on the S3 Storage endpoint field so
the create and edit forms go through the same URL-normalization path as
webhook settings. Adds a matching guard inside S3Storage::testConnection()
so background callers (scheduled backups, database import reuse) also
validate the endpoint before building the S3 client.

Also fixes an IPv6-bracket edge case in SafeWebhookUrl so `http://[::1]`
style hosts are normalized before the filter_var IP check — the rule's
own loopback test was already asserting this behaviour.
2026-04-20 11:50:19 +02:00
Andras Bacsai
af0a8badb3 refactor(backup): validate database backup upload file type and size
Add allowlist of backup file extensions (sql, sql.gz, tar, tgz, zip,
dump, bak, bson, archive, bz2, xz, and compound variants) and enforce
a 10 GiB maximum file size on the backup upload endpoint. Validation
runs early on each chunk using the dropzone metadata and again on the
assembled file. Also drops the unused createFilename helper and the
commented-out S3 block.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-20 11:45:00 +02:00
Andras Bacsai
410a9a6195 refactor(volumes): validate input and escape shell args
Tighten validation on volume name and host path inputs across Livewire + API storage endpoints and escape shell arguments in volume clone and compose preview cleanup paths.
2026-04-20 11:27:10 +02:00
Andras Bacsai
1f9dd5326f Merge remote-tracking branch 'origin/next' into audit-policies
# Conflicts:
#	tests/Feature/DatabaseBackupCreationApiTest.php
2026-04-19 17:40:12 +02:00
Andras Bacsai
a1b2ab124a
fix(api): use explicit team ID for S3 storage lookup in backup endpoints (#9655) 2026-04-19 15:28:13 +02:00
Andras Bacsai
5019c8db92 fix(api): use explicit team ID for S3 storage lookup in backup endpoints
Replace `ownedByCurrentTeam()` (session-based) with `ownedByCurrentTeamAPI($teamId)`
(explicit team ID) when resolving S3 storage in create_backup and update_backup.
Session-based team resolution is unreliable in API context where auth is token-based.

Add `S3Storage::ownedByCurrentTeamAPI(int $teamId)` scope and update feature tests
to use real model instances instead of Mockery mocks.
2026-04-19 15:26:47 +02:00
Andras Bacsai
43f33d94ad Merge remote-tracking branch 'origin/next' into audit-policies
# Conflicts:
#	app/Http/Controllers/Api/SecurityController.php
#	app/Http/Controllers/Api/ServersController.php
#	app/Livewire/Admin/Index.php
#	app/Livewire/Destination/Show.php
#	app/Livewire/NavbarDeleteTeam.php
#	app/Livewire/Project/Application/Previews.php
#	app/Livewire/Project/DeleteProject.php
#	app/Livewire/Project/Shared/ResourceOperations.php
#	app/Livewire/Server/Resources.php
#	app/Livewire/Server/ValidateAndInstall.php
#	app/Livewire/Storage/Show.php
#	resources/views/livewire/dashboard.blade.php
#	resources/views/livewire/project/application/heading.blade.php
#	resources/views/livewire/project/database/heading.blade.php
#	resources/views/livewire/project/service/heading.blade.php
#	resources/views/livewire/project/shared/environment-variable/show.blade.php
#	resources/views/livewire/project/shared/scheduled-task/show.blade.php
#	tests/Feature/Security/TrustHostsMiddlewareTest.php
2026-04-19 15:19:37 +02:00
Andras Bacsai
0620496c5f fix(server): exclude persistent resources from container prune
Prevent docker container prune from removing containers labeled as
database, application, or service types. Previously only proxy containers
were excluded, risking accidental cleanup of active resources.
2026-04-19 15:17:47 +02:00
Andras Bacsai
371e883c75
refactor(api): validate and throttle feedback endpoint (#9653) 2026-04-19 14:50:03 +02:00
Andras Bacsai
5bf4bb9e80
feat(api): add DELETE endpoint for preview deployments by PR id (#9614) 2026-04-19 14:43:32 +02:00
Andras Bacsai
e7bbd45408 refactor(api): validate and throttle feedback endpoint
- Validate content (required string, min:10, max:2000) in OtherController@feedback
- Register 'feedback' named rate limiter (3/min per user or IP) in RouteServiceProvider
- Apply throttle:feedback middleware to POST /api/feedback
- Forward to Discord with allowed_mentions.parse=[] and a 5s HTTP timeout

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-19 14:41:47 +02:00
Andras Bacsai
bafb9a5a8b refactor(webhook): encrypt manual webhook secrets and tighten HMAC verification
- Auto-generate a 40-char random secret for each manual_webhook_secret_* column on Application creation so new apps are never left with an empty secret.
- Add encrypted cast for the four webhook-secret columns; backfill migration re-encrypts existing plaintext values and fills missing ones.
- Reject webhook deliveries when the stored secret is empty (GitHub, GitLab, Bitbucket, Gitea manual endpoints).
- Bitbucket: require the sha256 algorithm prefix on X-Hub-Signature instead of trusting the client-supplied algo.
- GitLab: drop the ?? '' fallback on the token comparison.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-19 12:52:23 +02:00
Andras Bacsai
33518b24a2
refactor: tighten team scoping on resource creation and admin nav (#9651) 2026-04-19 12:01:11 +02:00
Andras Bacsai
f77cc91b83 refactor(admin): use named routes for admin index navigation
Replace Referer-based redirects in Admin Index back() and switchUser()
with named routes (admin.index and dashboard) for consistent navigation
behavior independent of the request header.

Add tests verifying back() returns to admin.index, switchUser routes to
the dashboard, and the Referer header is no longer consulted.
2026-04-19 11:58:52 +02:00
Andras Bacsai
a478ac66eb refactor: scope destination and resource lookups by current team
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.
2026-04-19 11:55:12 +02:00
Jan Thiel
a4b27641c8 feat(hetzner): add endpoints and UI for attaching firewalls and internal networks to the Server Creation dialog 2026-04-19 06:12:50 +02:00
Andras Bacsai
bceb5f28dc feat(applications): add DELETE endpoint for preview deployments by PR id
Add `DELETE /api/v1/applications/{uuid}/previews/{pull_request_id}` to
cancel active deployments, stop containers, and delete the preview
record via `CleanupPreviewDeployment`. Includes OpenAPI annotations,
input validation, and full feature test coverage.
2026-04-17 13:29:11 +02:00
Andras Bacsai
451b7376ed Merge remote-tracking branch 'origin/next' into feat/railpack 2026-04-17 07:01:27 +02:00
Andras Bacsai
3a8f52ce16 fix(team): mark servers unreachable when subscription ends
Set unreachable_count to 3 and unreachable_notification_sent to true
on all team servers in subscriptionEnded(), so the existing cleanup
command can pick them up after the 7-day grace period.

Also adds feature tests for the subscription-ended cleanup flow and
casts server IP to string in existing unreachable server tests to fix
type comparison.
2026-04-15 15:12:29 +02:00
Andras Bacsai
3fa4ea9ad3
fix(git): preserve ssh scheme URLs with custom ports (#9425) 2026-04-14 15:31:31 +02:00
Andras Bacsai
16d9c02e73 fix(install): use Rocky Linux RHEL Docker repository
Add a Rocky-specific Docker install path to the stable and nightly install scripts, using Docker's documented RHEL repository flow. Include a unit test to lock in the Rocky repo selection and command set.
2026-04-14 10:31:01 +02:00
Andras Bacsai
0627db5342 Merge remote-tracking branch 'origin/next' into feat/railpack 2026-04-10 12:20:09 +02:00
Andras Bacsai
0d8a95473a fix(ui): improve responsive project headings and controls
Refine mobile layout for project resource pages by making breadcrumbs and status blocks responsive, improving dropdown and checkbox touch behavior, and adding support for custom modal triggers. Add feature tests covering breadcrumb visibility and responsive checkbox layout.
2026-04-09 19:51:31 +02:00
Andras Bacsai
33f260a655 fix(deployments): use full-height deployment logs layout
Adjust the deployment view container classes so the logs panel fills the available viewport height instead of capping at 30rem. Add a feature test to lock in the full-height layout classes and prevent regressions.
2026-04-09 19:27:19 +02:00
Andras Bacsai
3c51b1aacc fix(railpack): pass command overrides through supported prepare/build args
Use Railpack's install env handling and dedicated CLI flags for build/start overrides, and forward install commands into docker build secrets so image builds stay aligned with prepare-time configuration. Update the railpack config test to cover the new command format.
2026-04-09 19:01:52 +02:00
Andras Bacsai
d7e1b7ec37 feat(railpack): add config merging, beta badge, and nodejs seeder example
- Implement railpack.json + generated config deep merging logic in
  ApplicationDeploymentJob with JSON validation and assoc array checks
- Label Railpack as "Beta" in all build pack selectors and show a
  visible beta badge when railpack is selected in new-app forms
- Add railpack-nodejs Fastify example to ApplicationSeeder
- Add ApplicationSeederTest and ApplicationDeploymentRailpackConfigTest
  covering config merge behavior and seeder correctness
2026-04-09 18:45:42 +02:00
Andras Bacsai
0649a424b8 fix(buildpack): revert default build pack to nixpacks and reorder selector
Change default build_pack from railpack back to nixpacks in all new
application flows (GithubPrivateRepository, GithubPrivateRepositoryDeployKey,
PublicGitRepository) and reorder the build pack dropdown so Nixpacks
appears before Railpack across all relevant views.

Add feature tests covering the nixpacks default and selector ordering.
2026-04-09 17:48:17 +02:00
Tristan Rhodes
519a186e84 fix: normalize oauth emails before matching users 2026-04-09 09:38:56 -06:00
Andras Bacsai
f573ad28a0 Merge remote-tracking branch 'origin/next' into feat/railpack 2026-04-09 17:12:26 +02:00
Andras Bacsai
7d2c776ae7 fix(team): transfer instance-wide sources to root team on deletion
Instead of nullifying source references on applications when a team is
deleted, transfer instance-wide GitHub/GitLab apps to the root team
(team_id=0) so they remain available to other teams that depend on them.

Non-instance-wide sources are still deleted along with the team.
2026-04-09 14:51:52 +02:00
Andras Bacsai
ad662e5560 Merge remote-tracking branch 'origin/next' into 8172-investigate-user-delete-bug 2026-04-09 14:51:22 +02:00
Andras Bacsai
dbd2b68a08 fix(upgrade): clear stale upgrade flag when version is already current
Refactor upgrade state initialization into a shared `refreshUpgradeState()`
method used by both `mount()` and `checkUpdate()`. The method now uses
`version_compare` to validate upgrade availability and clears the
`new_version_available` flag in InstanceSettings when the current version
is already equal to or newer than the latest version, preventing stale
upgrade notifications from persisting after a successful update.
2026-04-09 14:31:12 +02:00
Andras Bacsai
02558d8672 Merge remote-tracking branch 'origin/next' into pr-7774-fix-upgrade-notification-modal 2026-04-09 14:16:28 +02:00
Andras Bacsai
e012e98a34 Merge remote-tracking branch 'origin/next' into 8172-investigate-user-delete-bug 2026-04-09 14:08:54 +02:00
Andras Bacsai
e36ae82d9d fix(validation): allow quoted shell args in docker options
Permit single-quoted arguments in SHELL_SAFE_COMMAND_PATTERN while
keeping dangerous metacharacters blocked, and add security test cases
for quoted --entrypoint and --hostname values.
2026-04-08 14:21:49 +02:00
Iisyourdad
d2ada90a47 fix(git): harden ssh URL normalization 2026-04-07 22:41:15 -05:00
Andras Bacsai
8f7bb449da Merge remote-tracking branch 'origin/next' into 8172-investigate-user-delete-bug 2026-04-05 18:15:54 +02:00
Andras Bacsai
3f564f9b2e fix(user-deletion): handle GitHub app sources across team cleanup
Limit team cleanup to apps owned by the deleted team and nullify cross-team application source references before deleting team-owned sources. Adds feature tests covering user deletion with GitHub app-backed applications, preserving system-wide apps, and nullifying external source links.
2026-04-05 18:08:06 +02:00
Iisyourdad
f877985e56 fix(git): preserve ssh scheme URLs with custom ports 2026-04-04 14:49:34 -05:00
Andras Bacsai
ffb5045c6a fix(backups): enforce retention and clean up stale executions
Add `WithoutOverlapping` middleware to `DatabaseBackupJob` keyed by backup ID
with timeout-based lock expiry to prevent concurrent runs.

Mark long-running backup executions as failed when they exceed the stale
time threshold, and add periodic retention enforcement in
`CleanupInstanceStuffsJob` with cache-based throttling.

Also add float casts for retention max-storage fields on
`ScheduledDatabaseBackup` and comprehensive feature tests covering
overlap middleware, stale detection, casts, and retention behavior.
2026-04-03 11:33:21 +02:00
Andras Bacsai
7542c71dc4 Merge remote-tracking branch 'origin/next' into 2731-investigate-failed-git-clone 2026-04-03 09:05:13 +02:00
Andras Bacsai
968508583d fix(project): handle slash branches in public repo URLs
Parse `/tree/...` URLs by first capturing the full branch candidate, then
iteratively resolving valid branch names for GitHub API lookups and deriving
the remaining path as base directory. Also adjust env var editor/input view
classes (`font-sans`, `w-full`) and add/extend feature tests for both branch
parsing and multiline toggle rendering.
2026-04-01 09:11:56 +02:00
Andras Bacsai
c2a3be152e test(upgrade): add mount tests for cached and fallback versions
Covers Upgrade Livewire component mount behavior for:
- initializing latest version from cached versions data
- falling back to 0.0.0 when versions cache is unavailable
2026-03-31 17:28:24 +02:00
Andras Bacsai
2abb073b52 Merge remote-tracking branch 'origin/next' into 9076-investigate-pre-deployment 2026-03-31 16:49:43 +02:00
Andras Bacsai
da5b003971 Merge remote-tracking branch 'origin/next' into unreachable-server-backoff 2026-03-31 16:46:22 +02:00
Andras Bacsai
3961077b90 feat(forms): make textarea monospace opt-in and improve multiline toggle
Add `monospace` prop to Textarea component so font-mono is no longer
applied by default. Apply it explicitly to env variable editors, private
key fields, and shared variable forms where monospace is appropriate.

Use Alpine.js x-data/x-model to make the multiline toggle reactive
without a full Livewire round-trip. Add wire:key on the input/textarea
wrappers to force proper DOM replacement when switching modes.
2026-03-31 15:37:42 +02:00
Andras Bacsai
acb716cb90 fix(shared-variables): support direct mount params and comment field for server variables
Allow SharedVariables Livewire components (Environment, Project, Server)
to accept UUID parameters directly via mount() instead of relying solely
on route parameters. This enables Livewire component testing without a
live route context.

Also adds comment field support when saving/updating server shared
environment variables, guards PostgreSQL-specific migration statements
from running under SQLite (test environment compatibility), and expands
the feature test suite with server shared variable scenarios including
inline comment preservation and update behaviour.
2026-03-31 14:58:01 +02:00
Andras Bacsai
466eb8504e refactor(models): extract defaultStandaloneDockerAttributes method on Server
Extract duplicated inline StandaloneDocker attribute arrays in the
Server boot lifecycle into a dedicated method, eliminating repetition
between the root-server (id=0) and normal-server paths.

Also harden the shared_environment_variables migration by wrapping
DDL statements in DB::transaction() and using DROP CONSTRAINT IF EXISTS
to make the migration safely re-runnable.

Add unit test covering the extracted method to verify uuid is always
present in bootstrap attributes.
2026-03-31 14:44:45 +02:00
Andras Bacsai
1a603a10ed fix(models): replace forceFill/forceCreate with fill/create and add fillable guards
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.
2026-03-31 13:45:31 +02:00
Andras Bacsai
7638912fdc fix(github): reset branch state when refreshing repositories
Clear `branches` and `total_branches_count` in `loadRepositories` to avoid stale branch data after repo refreshes. Update the Livewire view to use the shared loading button pattern for refresh/load actions, and expand feature coverage for repository refresh behavior and refresh button visibility.
2026-03-31 12:50:19 +02:00
Andras Bacsai
25c0c88eb2 Merge remote-tracking branch 'origin/next' into feat/refresh-repos 2026-03-31 12:37:38 +02:00
Andras Bacsai
2692496726 fix(database): refresh SSL/status state and harden clone writes
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.
2026-03-31 09:29:36 +02:00
Bakr Elsherif
2af16cd25e
Merge branch 'next' into next 2026-03-31 00:38:18 +03:00
Andras Bacsai
f09115afdc Merge remote-tracking branch 'origin/next' into feat/refresh-repos 2026-03-30 17:30:14 +02:00
Tobias Thiele
7f46b2ed71 Populate docker_compose_domains for dockercompose apps
Add logic to populate docker_compose_domains in applicationParser
for dockercompose build packs, ensuring proper domain handling
for KEY-based SERVICE_FQDN variables.
2026-03-30 14:59:20 +02:00
Andras Bacsai
61f47cc7ee feat(deployments): support Docker image tags for preview deployments
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
2026-03-30 13:35:35 +02:00
Andras Bacsai
3fddc795f6
refactor: define explicit fillable attributes on all Eloquent models (#9282) 2026-03-30 13:11:58 +02:00
Andras Bacsai
850c37bedd fix(database): auto-generate missing CA cert on SSL regeneration
Prevent null CA certificate access during database SSL certificate regeneration
across KeyDB, MariaDB, MongoDB, MySQL, PostgreSQL, and Redis components.

If no CA certificate exists, attempt to generate one and re-query; if still
missing, dispatch a clear error and stop regeneration gracefully.

Add `SslCertificateRegenerationTest` coverage for missing-CA and CA-query
scenarios to prevent regressions.
2026-03-30 13:10:49 +02:00
Andras Bacsai
1da1f32f0e refactor: use forceCreate() for internal model creation
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.
2026-03-30 13:04:11 +02:00
Michael Jathe
2b573ef5ec
Merge branch 'next' into feat/api/tag-management 2026-03-30 10:04:00 +02:00
Andras Bacsai
09f1c71a76 Merge remote-tracking branch 'origin/next' into refactor/sync-model-attributes 2026-03-30 08:14:32 +02:00
Andras Bacsai
c0c0349880 refactor(models): add fillable attributes for database configuration options
Add explicit fillable attributes to Service and all Standalone* database models
for new configuration options: public_port_timeout, enable_ssl, ssl_mode,
is_log_drain_enabled, is_include_timestamps, and custom_docker_run_options.

Add tests to MassAssignmentProtectionTest to verify these attributes are
properly protected by mass assignment protection across all relevant models.
2026-03-30 08:11:23 +02:00
Andras Bacsai
4ec9b7ef69 fix(clone): include uuid field when cloning persistent volumes
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.
2026-03-30 00:06:45 +02:00
Andras Bacsai
f267a28cb2
fix: harden GetLogs Livewire component properties (#9229) 2026-03-29 21:29:23 +02:00
Andras Bacsai
7b3b6fa6ef
fix(application): persist redirect value in setRedirect (#9279) 2026-03-29 21:03:14 +02:00
Andras Bacsai
b3256d4df1 fix(security): harden model assignment and sensitive data handling
Restrict mass-assignable attributes across user/team/redis models and
switch privileged root/team creation paths to forceFill/forceCreate.

Encrypt legacy ClickHouse admin passwords via migration and cast the
correct ClickHouse password field as encrypted.

Tighten API and runtime exposure by removing sensitive team fields from
responses and sanitizing Git/compose error messages.

Expand security-focused feature coverage for command-injection and mass
assignment protections.
2026-03-29 20:56:04 +02:00
Andras Bacsai
3fde1e0f9f fix(application): persist redirect value in setRedirect
Assign the selected redirect option before validation so valid changes are saved.
Add feature tests to verify redirect persistence and rejection when no www domain exists.
2026-03-29 20:50:03 +02:00
Andras Bacsai
a5840501b4 fix(forms): use Alpine state for password visibility toggles
Replace shared `changePasswordFieldType` JS with component-local Alpine logic
across input, textarea, and env-var-input components. This keeps toggle
behavior consistent, resets visibility on `success` events, and preserves
`truncate` styling only when showing plaintext on enabled fields.

Also adds `PasswordVisibilityComponentTest` to verify Alpine bindings are
rendered and legacy handler references are removed.
2026-03-29 20:47:36 +02:00
Andras Bacsai
9e96a20a49
fix: add validation and escaping for Docker network names (#9228) 2026-03-29 20:46:39 +02:00
Andras Bacsai
1027c73d0f
refactor: scope server and project queries to current team (#9230) 2026-03-29 20:28:21 +02:00
Michael Jathe
23d5b854e9 feat(api): add tag management endpoints for applications, databases, and services
Add CRUD tag endpoints (GET/POST/DELETE) as sub-resources for applications,
databases, and services. Add team-level GET /tags endpoint. Extend all
resource creation endpoints to accept an optional tags array.

Uses a shared HandlesTagsApi trait to avoid duplication across controllers.
Tags are race-safe via syncWithoutDetaching(), garbage-collected when orphaned,
and sanitized (strip_tags + lowercase).
2026-03-29 16:02:05 +02:00
Andras Bacsai
3ba4553df5 fix(security): enforce team-scoped project/env lookups in onboarding
Use firstOrFail() for team-scoped project and environment lookups across
new-project Livewire flows so missing or cross-team UUIDs fail closed.
Also dispatch an error when boarding selects a non-owned project, and
update IDOR feature tests for the new error/exception behavior.
2026-03-29 15:55:03 +02:00
Andras Bacsai
96ae9ade23
fix: add input validation for install/build/start command fields (#9227) 2026-03-29 15:48:30 +02:00
Bakr
8ad65a0ef8 eat(api): add service-applications API to manage service applications 2026-03-29 06:03:47 +03:00
Andras Bacsai
72118d61f9 feat(databases): add public port timeout configuration
Add support for configuring public port timeout on databases via API:
- Add public_port_timeout field to schema documentation with 3600s default
- Add validation rules (integer|nullable|min:1)
- Update all database type configurations to support the field
- Add comprehensive test coverage for the feature
2026-03-28 17:08:02 +01:00
Andras Bacsai
3b2e6e11f1
refactor: use random_int() for email change verification codes (#9226) 2026-03-28 15:18:00 +01:00
Andras Bacsai
377ce24b6d
Add URL validation for notification webhook fields (#9224) 2026-03-28 14:39:27 +01:00
Andras Bacsai
0b8c75f8ed fix(webhooks): add validation to block unsafe webhook URLs
Prevent server-side request forgery (SSRF) attacks by validating webhook URLs before sending requests. Blocks loopback addresses, cloud metadata endpoints, and localhost URLs.

- Add SafeWebhookUrl rule validation in SendWebhookJob.handle()
- Log warning when unsafe URLs are rejected
- Add comprehensive unit tests covering valid and invalid URL scenarios
2026-03-28 14:23:08 +01:00
Andras Bacsai
91ab0b38d6
refactor: move admin route into middleware group (#9225) 2026-03-28 14:18:16 +01:00
Andras Bacsai
ad694275b0 Merge remote-tracking branch 'origin/next' into fix/harden-getlogs-livewire-properties 2026-03-28 14:10:15 +01:00
Andras Bacsai
67a4fcc2ab fix: add mass assignment protection to models
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.
2026-03-28 12:32:57 +01:00
Andras Bacsai
e36622fdfb refactor: scope server and project queries to current team
Ensure Server and Project lookups in Livewire components and API
controllers use team-scoped queries (ownedByCurrentTeam / whereTeamId)
instead of unscoped find/where calls. This enforces consistent
multi-tenant isolation across all user-facing code paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 12:29:08 +01:00
Andras Bacsai
3d1b9f53a0 fix: add validation and escaping for Docker network names
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>
2026-03-28 12:28:59 +01:00
Andras Bacsai
48ba4ece3c fix: harden GetLogs Livewire component with locked properties and input validation
Add #[Locked] attributes to security-sensitive properties (resource, servicesubtype,
server, container) to prevent client-side modification via Livewire wire protocol.
Add container name validation using ValidationPatterns::isValidContainerName() and
server ownership authorization via Server::ownedByCurrentTeam() in both getLogs()
and downloadAllLogs() methods.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 12:28:54 +01:00
Andras Bacsai
c9922c30c2 fix: add input validation for install/build/start command fields
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>
2026-03-28 12:28:29 +01:00
Andras Bacsai
f493b96be3 refactor: use random_int() for email change verification codes
Replace mt_rand/rand with random_int for stronger randomness guarantees
in verification code generation and Blade component keying.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 12:25:54 +01:00
Andras Bacsai
aea201fcba refactor: move admin route into middleware group and harden authorization
Move the admin panel route into the existing auth middleware group and
replace client-side redirects with server-side abort calls in the
Livewire component. Extract shared authorization logic into reusable
private methods.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 12:24:40 +01:00
Andras Bacsai
564cd8368b fix: add URL validation for notification webhook fields
Add SafeWebhookUrl validation rule to notification webhook URL fields
(Slack, Discord, custom webhook) to enforce safe URL patterns including
scheme validation and hostname checks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 12:22:59 +01:00
Andras Bacsai
98569e4edb
fix: use server-side config for password reset URL generation (#9193) 2026-03-28 12:20:42 +01:00
Andras Bacsai
25dcde6a47
fix: sanitize error output in server validation logs (#9197) 2026-03-28 12:13:50 +01:00
Andras Bacsai
e396c70903 refactor: simplify TrustHosts middleware and use APP_URL as base_url fallback
- 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)
2026-03-28 12:12:48 +01:00
Andras Bacsai
638f1d37f1 feat(subscription): add billing interval to price preview
Extract and return the billing interval (month/year) from subscription pricing
data in fetchPricePreview. Update the view to dynamically display the correct
billing period based on the preview response instead of using static PHP logic.
2026-03-27 19:05:13 +01:00
Andras Bacsai
ba6f0cdb38 Merge remote-tracking branch 'origin/next' into fix/trust-hosts-url-generation 2026-03-27 14:14:36 +01:00
Andras Bacsai
af3826eac0 feat(reset-password): add IPv6 support and header poisoning protection
- 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
2026-03-27 14:14:01 +01:00
Andras Bacsai
f2e4879742 Merge remote-tracking branch 'origin/next' into feat/refresh-repos 2026-03-26 19:00:08 +01:00
Andras Bacsai
e1d4b4682e fix: harden TrustHosts middleware and use base_url() for password reset links
- Fix circular cache dependency in TrustHosts where handle() checked cache
  before hosts() could populate it, causing host validation to never activate
- Validate both Host and X-Forwarded-Host headers against trusted hosts list
  (X-Forwarded-Host is checked before TrustProxies applies it to the request)
- Use base_url() instead of url() for password reset link generation so the
  URL is derived from server-side config (FQDN / public IP) instead of the
  request context
- Strip port from X-Forwarded-Host before matching (e.g. host:443 → host)
- Add tests for host validation, cache population, and reset URL generation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 18:39:54 +01:00
Andras Bacsai
103d5b6c06 fix: sanitize error output in server validation logs
Escape dynamic error messages with htmlspecialchars() before
concatenating into HTML strings stored in validation_logs. Add a
Purify-based mutator on Server model as defense-in-depth, with a
dedicated HTMLPurifier config that allows only safe structural tags.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 18:36:36 +01:00
Andras Bacsai
25d424c743 refactor: split invitation endpoint into GET (show) and POST (accept)
Refactor the invitation acceptance flow to use a landing page pattern:
- GET shows invitation details (team name, role, confirmation button)
- POST processes the acceptance with proper form submission
- Remove unused revoke GET route (handled by Livewire component)
- Add Blade view for the invitation landing page
- Add feature tests for the new invitation flow

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 14:30:27 +01:00
Andras Bacsai
0fce7fa948 fix: add URL validation for GitHub source api_url and html_url fields
Add SafeExternalUrl validation rule that ensures URLs point to
publicly-routable hosts. Apply to all GitHub source entry points
(Livewire Create, Livewire Change, API create and update).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 13:45:33 +01:00
Andras Bacsai
3e0d48faea refactor: simplify remote process chain and harden ActivityMonitor
- 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>
2026-03-26 13:26:16 +01:00
Andras Bacsai
d2064dd499 fix(storage): use escapeshellarg for volume names in shell commands
Add proper shell escaping for persistent volume names when used in
docker volume rm commands. Also add volume name validation pattern
to ValidationPatterns for consistent input checking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 11:06:30 +01:00
Andras Bacsai
dd2c9c291a feat(jobs): implement exponential backoff for unreachable servers
Reduce load on unreachable servers by implementing exponential backoff
during connectivity failures. Check frequency decreases based on
consecutive failure count:
  0-2: every cycle
  3-5: ~15 min intervals
  6-11: ~30 min intervals
  12+: ~60 min intervals

Uses server ID hash to distribute checks across cycles and prevent
thundering herd.

ServerCheckJob and ServerConnectionCheckJob increment unreachable_count
on failures. ServerManagerJob applies backoff logic before dispatching
checks. Includes comprehensive test coverage.
2026-03-26 10:51:36 +01:00
Andras Bacsai
d77e4c864f
fix(backup): use escapeshellarg for credentials in backup commands (#9175) 2026-03-26 07:50:09 +01:00
Andras Bacsai
fecb80b596
fix(storage): consistent path validation and escaping for file volumes (#9176) 2026-03-26 07:44:46 +01:00
Andras Bacsai
3fdce06b65 fix(storage): consistent path validation and escaping for file volumes
Ensure all file volume paths are validated and properly escaped before
use. Previously, only directory mount paths were validated at the input
layer — file mount paths now receive the same treatment across Livewire
components, API controllers, and the model layer.

- Validate and escape fs_path at the top of saveStorageOnServer() before
  any commands are built
- Add path validation to submitFileStorage() in Storage Livewire component
- Add path validation to file mount creation in Applications, Services,
  and Databases API controllers
- Add regression tests for path validation coverage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 23:44:37 +01:00
Andras Bacsai
952f324797 fix(backup): use escapeshellarg for credentials in database backup commands
Apply proper shell escaping to all user-controlled values interpolated into
backup shell commands (PostgreSQL username/password, MySQL/MariaDB root
password, MongoDB URI). Also URL-encode MongoDB credentials before embedding
in connection URI. Adds unit tests for escaping behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 23:43:57 +01:00
Andras Bacsai
6f163ddf02 fix(deployment): normalize whitespace in pre/post deployment commands
Ensure pre_deployment_command and post_deployment_command have consistent
whitespace handling, matching the existing pattern used for health_check_command.
Adds regression tests for the normalization behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 20:57:17 +01:00
Andras Bacsai
ae31111813 fix(livewire): add input validation to unmanaged container operations
Add container name validation and shell argument escaping to
startUnmanaged, stopUnmanaged, restartUnmanaged, and restartContainer
methods, consistent with existing patterns used elsewhere in the
codebase.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 20:42:00 +01:00
Andras Bacsai
e2ba44d0c3 fix(validation): allow ampersands and quotes in shell-safe command pattern
Previously, the SHELL_SAFE_COMMAND_PATTERN was overly restrictive and blocked
legitimate characters needed for common Docker operations:

- Allow & for command chaining with && in multi-step build commands
- Allow " for build arguments with spaces (e.g., --build-arg KEY="value")

Update validation messages to reflect the new allowed operators and refactor
code to use imports instead of full class paths for better readability.
2026-03-25 20:27:21 +01:00
Andras Bacsai
d486bf09ab fix(livewire): add Locked attributes and consolidate container name validation
- Add #[Locked] to server-set properties on Import component (resourceId,
  resourceType, serverId, resourceUuid, resourceDbType, container) to
  prevent client-side modification via Livewire wire protocol
- Add container name validation in runImport() and restoreFromS3()
  using shared ValidationPatterns::isValidContainerName()
- Scope server lookup to current team via ownedByCurrentTeam()
- Consolidate duplicate container name regex from Import,
  ExecuteContainerCommand, and Terminal into shared
  ValidationPatterns::isValidContainerName() static helper
- Add tests for container name validation, locked attributes, and
  team-scoped server lookup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 20:21:39 +01:00
Andras Bacsai
0fed553207 fix(settings): require instance admin authorization for updates page 2026-03-25 19:33:51 +01:00
Andras Bacsai
bc91b41f92
fix(terminal): apply authorization middleware to terminal bootstrap routes (#9169) 2026-03-25 18:44:08 +01:00
Andras Bacsai
847166a3f8 fix(terminal): apply authorization middleware to terminal bootstrap routes
Apply the existing `can.access.terminal` middleware to `POST /terminal/auth`
and `POST /terminal/auth/ips` routes, consistent with the `GET /terminal` route.

Adds regression tests covering unauthenticated, member, admin, and owner roles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:56:37 +01:00
Andras Bacsai
99043600ee fix(backup): validate MongoDB collection names in backup input
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>
2026-03-25 16:52:06 +01:00
Andras Bacsai
207002dbb7 Merge remote-tracking branch 'origin/next' into feat/railpack 2026-03-25 16:45:30 +01:00
Andras Bacsai
a94517f452 fix(api): validate server ownership in domains endpoint and scope activity lookups
- Add team-scoped server validation to domains_by_server API endpoint
- Filter applications and services to only those on the requested server
- Scope ActivityMonitor activity lookups to the current team
- Fix query param disambiguation (query vs route param) in domains endpoint
- Fix undefined $ip variable in services domain collection

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:20:53 +01:00
Andras Bacsai
811ee5d327 refactor(jobs): extract container resolution logic for deployment commands
Extract common container selection logic into resolveCommandContainer() method
that handles both single and multi-container app scenarios. This consolidates
duplicated code from run_pre_deployment_command() and run_post_deployment_command()
while improving error messaging and test coverage.
2026-03-25 14:09:07 +01:00
Andras Bacsai
3034e89edb feat(preview-env): add production variable fallback for docker-compose
When preview environment variables are configured, fall back to production
variables for keys not overridden by preview values. This ensures variables
like DB_PASSWORD that exist only in production are available in the preview
.env file, enabling proper ${VAR} interpolation in docker-compose YAML.

Fallback only applies when preview variables are configured, preventing
unintended leakage of production values when previews aren't in use.

Also improves UI by hiding the Domains section when only database services
are present, and simplifies the logs view by removing status checks.
2026-03-25 13:26:50 +01:00
Andras Bacsai
14a7f8646c fix(backup): prevent notification failures from affecting backup status
- Wrap notification calls in try-catch blocks to log failures instead
- Prevent failed() method from overwriting successful backup status
- Skip failure notifications if backup already completed successfully
- Ensures post-backup errors (e.g. notification failures) never
  retroactively mark successful backups as failed

Fixes #9088
2026-03-25 12:43:47 +01:00
Andras Bacsai
5c460dd2a1
fix(proxy): validate stored config matches proxy type (#9146) 2026-03-24 21:53:48 +01:00
Andras Bacsai
6a14a12a58 fix(parsers): preserve ${VAR} references in compose instead of resolving to DB values
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
2026-03-24 21:52:36 +01:00
Andras Bacsai
b8e52c6a45 feat(proxy): validate stored config matches current proxy type
Add validation in GetProxyConfiguration to detect when stored proxy config
belongs to a different proxy type (e.g., Traefik config on a Caddy server)
and trigger regeneration with a warning log. Clear cached proxy configuration
and settings when proxy type is changed to prevent stale configs from being
reused. Includes tests verifying config rejection on type mismatch and
graceful fallback on invalid YAML.
2026-03-24 21:32:34 +01:00
Andras Bacsai
d3beeb2d00 fix(subscription): prevent duplicate subscriptions with updateOrCreate
- Replace manual subscription create/update logic with updateOrCreate() and firstOrCreate() to eliminate race conditions
- Add validation in PricingPlans to prevent subscribing if team already has active subscription
- Improve error handling for missing team_id in customer.subscription.updated event
- Add tests verifying subscriptions are updated rather than duplicated
2026-03-24 10:52:41 +01:00
Andras Bacsai
233f53494e
fix(team): resolve server limit checks for API token authentication (#9123) 2026-03-24 08:12:56 +01:00
Andras Bacsai
988dd57cf4 feat(validation): make hostname validation case-insensitive and expand allowed characters
- 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
2026-03-24 08:03:08 +01:00
Andras Bacsai
2ed360f0e0 Merge remote-tracking branch 'origin/next' into feat/railpack 2026-03-23 21:58:33 +01:00
Andras Bacsai
e37cb98c7c refactor(team): make server limit methods accept optional team parameter
Allow serverLimit() and serverLimitReached() to accept an optional team
parameter instead of relying solely on the current session. This improves
testability and makes the methods more flexible by allowing them to work
without session state.

Add comprehensive tests covering various scenarios including no session,
team at limit, and team under limit.
2026-03-23 21:56:50 +01:00
Andras Bacsai
dac940807a fix(deployment): properly escape shell arguments in nixpacks commands
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.
2026-03-23 21:55:46 +01:00
Andras Bacsai
b931418c1e fix(github-webhook): handle unsupported event types gracefully
Add validation in manual and normal webhook handlers to reject GitHub
event types other than 'push' and 'pull_request'. Unsupported events
now return a graceful response instead of potentially causing
downstream errors. Includes tests for ping events, unsupported event
types, and unknown events.
2026-03-23 21:33:40 +01:00
Aditya Tripathi
cddbaf581f refactor(railpack): extract static image build, fix port logic, bump to v0.22.0
Extract build_railpack_static_image() into its own method, prevent port
override when is_static is set, bump Railpack to 0.22.0, and improve
test setup with beforeEach and correct polymorphic env var fields.
2026-03-23 19:02:10 +00:00
Aditya Tripathi
793077d74f feat(buildpack): add Railpack as a build pack option 2026-03-23 17:12:02 +00:00
Andras Bacsai
ae33447994 feat(storage): add storage endpoints and UUID support for databases and services
- 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
2026-03-23 15:15:02 +01:00
Andras Bacsai
f8f27fff13 refactor(scheduler): extract cron scheduling logic to shared helper
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
2026-03-23 10:37:49 +01:00
Andras Bacsai
6aa618e57f feat(jobs): add cache-based deduplication for delayed cron execution
Implements getPreviousRunDate() + cache-based tracking in shouldRunNow()
to prevent duplicate dispatch of scheduled jobs when queue delays push
execution past the cron minute. This resilience ensures jobs catch missed
windows without double-dispatching within the same cron window.

Updated scheduled job dispatches to include dedupKey parameter:
- Docker cleanup operations
- Server connection checks
- Sentinel restart checks
- Server storage checks
- Server patch checks

DockerCleanupJob now dispatches on the 'high' queue for faster processing.

Includes comprehensive test coverage for dedup behavior across different
cron schedules and delay scenarios.
2026-03-20 15:44:10 +01:00
Andras Bacsai
2bc8fe3dd7
fix(backup): throw explicit error when S3 storage missing or deleted (#9038) 2026-03-19 23:39:36 +01:00
Andras Bacsai
c00d5de03e feat(api): add database environment variable management endpoints
Add CRUD API endpoints for managing environment variables on databases:
- GET /databases/{uuid}/envs - list environment variables
- POST /databases/{uuid}/envs - create environment variable
- PATCH /databases/{uuid}/envs - update environment variable
- PATCH /databases/{uuid}/envs/bulk - bulk create environment variables
- DELETE /databases/{uuid}/envs/{env_uuid} - delete environment variable

Includes comprehensive test suite and OpenAPI documentation.
2026-03-19 23:29:50 +01:00
Andras Bacsai
fb76b68c08 feat(api): support comments in bulk environment variable endpoints
Add support for optional comment field on environment variables created or
updated through the bulk API endpoints. Comments are validated to a maximum
of 256 characters and are nullable. Updates preserve existing comments when
not provided in the request.
2026-03-19 22:17:55 +01:00
Andras Bacsai
8a164735cb fix(api): extract resource UUIDs from route parameters
Extract resource UUIDs from route parameters instead of request body
in ApplicationsController and ServicesController environment variable
endpoints. This prevents UUID parameters from being spoofed in the
request body.

- Replace $request->uuid with $request->route('uuid')
- Replace $request->env_uuid with $request->route('env_uuid')
- Add tests verifying route parameters are used and body UUIDs ignored
2026-03-19 21:56:58 +01:00
Andras Bacsai
ca3ae289eb feat(storage): add resources tab and improve S3 deletion handling
Add new Resources tab to storage show page displaying backup schedules using
that storage. Refactor storage show layout with navigation tabs for General
and Resources sections. Move delete action from form to show component.

Implement cascade deletion in S3Storage model to automatically disable S3
backups when storage is deleted. Improve error handling in DatabaseBackupJob
to throw exception when S3 storage is missing instead of silently returning.

- New Storage/Resources Livewire component
- Add resources.blade.php view
- Add storage.resources route
- Move delete() method from Form to Show component
- Add deleting event listener to S3Storage model
- Track backup count and current route in Show component
- Add #[On('submitStorage')] attribute to form submission
2026-03-19 11:42:29 +01:00
Andras Bacsai
d0b4dc1c63
fix(stripe): add error handling and resilience to subscription operations (#9030) 2026-03-18 15:38:59 +01:00
Andras Bacsai
566744b2e0 fix(stripe): add error handling and resilience to subscription operations
- Record refunds immediately before cancellation to prevent retry issues if cancel fails
- Wrap Stripe API calls in try-catch for refunds and quantity reverts with internal notifications
- Add null check in Team.subscriptionEnded() to prevent NPE when subscription doesn't exist
- Fix control flow bug in StripeProcessJob (add missing break statement)
- Cap dynamic server limit with MAX_SERVER_LIMIT in subscription updates
- Add comprehensive tests for refund failures, event handling, and null safety
2026-03-18 15:21:59 +01:00
Andras Bacsai
426a708374 feat(subscription): display next billing date and billing interval
Add current_period_end to refund eligibility checks and display next billing
date and billing interval in the subscription overview. Refactor the plan
overview layout to show subscription status more prominently.
2026-03-18 15:11:19 +01:00
Andras Bacsai
23f9156c73 Squashed commit from 'qqrq-r9h4-x6wp-authenticated-rce' 2026-03-18 13:53:01 +01:00
Andras Bacsai
d4bf011a8e Merge remote-tracking branch 'origin/next' into next 2026-03-16 21:38:07 +01:00
Andras Bacsai
6325e41aec fix(ssh): handle chmod failures gracefully and simplify key management
- Log warnings instead of silently failing when chmod 0600 fails
- Remove redundant refresh() call before SSH key validation
- Remove storeInFileSystem() call from updatePrivateKey() transaction
- Remove @unlink() of lock file after filesystem store
- Refactor unit tests to use real temp disk and anonymous class stub
  instead of reflection-only checks
2026-03-16 21:27:10 +01:00
Andras Bacsai
2ba62ffe02 Merge remote-tracking branch 'origin/next' into next 2026-03-16 21:22:32 +01:00
Andras Bacsai
9976645c25 Merge remote-tracking branch 'origin/next' into fix/ssh-sporadic-permission-denied 2026-03-16 21:15:30 +01:00
Andras Bacsai
15d6de9f41 fix(storages): hide PR suffix for services and fix instantSave logic
- Restrict "Add suffix for PR deployments" checkbox to non-service
  resources in both shared and service file-storage views
- Replace condition `is_preview_deployments_enabled` with `!$isService`
  for PR suffix visibility in storages/show.blade.php
- Fix FileStorage::instantSave() to use authorize + syncData instead
  of delegating to submit(), preventing unintended side effects
- Add $this->validate() to Storages/Show::instantSave() before saving
- Add response content schemas to storages API OpenAPI annotations
- Add additionalProperties: false to storage update request schema
- Rewrite PreviewDeploymentBindMountTest with behavioral tests of
  addPreviewDeploymentSuffix instead of file-content inspection
2026-03-16 21:10:00 +01:00
Andras Bacsai
fe1aa94144 Merge remote-tracking branch 'origin/next' into fix/ssh-sporadic-permission-denied 2026-03-16 20:26:56 +01:00
Andras Bacsai
0ffcee7a4d Squashed commit from '4fhp-investigate-os-command-injection' 2026-03-16 16:40:16 +01:00
Andras Bacsai
add16853a8 feat(preview): add configurable PR suffix toggle for volumes
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.
2026-03-16 14:54:22 +01:00
Andras Bacsai
5b424f1f0e fix(preview): exclude bind mounts from preview deployment suffix
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
2026-03-16 13:33:58 +01:00
pannous
2f96a759df test: add behavioral ssh key stale-file regression 2026-03-16 10:40:22 +01:00
pannous
4bf94fac2d fix: prevent sporadic SSH permission denied by validating key content
The root cause of sporadic "Permission denied (publickey)" errors was
that validateSshKey() only checked if the key file existed on disk,
never verifying its content matched the database. When keys were rotated
or updated, the stale file persisted and SSH used the wrong key.

Changes:
- validateSshKey() now refreshes key from DB and compares file content
- Server saved event detects private_key_id changes to invalidate mux
- PrivateKey storeInFileSystem() uses file locking to prevent races
- PrivateKey saved event auto-resyncs file on key content changes
- Enforces 0600 permissions on key files

Fixes coollabsio/coolify#7724
2026-03-15 03:06:21 +01:00
Niklas Wichter
2f8df2f9bd fix(test): align test setup with project conventions 2026-03-13 17:25:00 +01:00
Andras Bacsai
74d591e6e9
feat(server): auto-fetch server metadata after validation (#8964) 2026-03-13 17:08:15 +01:00
Andras Bacsai
1936bb08bf feat(server): auto-fetch server metadata after validation
Server metadata is now automatically gathered when server validation completes successfully, both in the async job and Livewire component. This ensures server details (OS, CPU count, etc.) are populated immediately after validation passes, improving the user experience without requiring manual metadata fetching.

Tests added to verify gatherServerMetadata is called on successful validation and skipped when validation fails.
2026-03-13 17:07:50 +01:00
Niklas Wichter
94700347f8 test: add move resource API tests 2026-03-13 17:05:00 +01:00
Andras Bacsai
c39a287b47 feat(compose-preview): populate fqdn from docker_compose_domains
The generate_preview_fqdn_compose method now extracts and populates the fqdn field from docker_compose_domains, making it available for webhook notifications. This handles multiple domains across services and gracefully sets fqdn to null when no domains are configured.
2026-03-13 17:02:05 +01:00
Andras Bacsai
d5b3a0380c
fix(docker-compose): respect preserveRepository when injecting --project-directory (#8956) 2026-03-13 13:55:50 +01:00
Andras Bacsai
a97612b29e fix(docker-compose): respect preserveRepository when injecting --project-directory
When adding --project-directory to custom docker compose start commands,
use the application's host workdir if preserveRepository is true, otherwise
use the container workdir. Add tests for both scenarios and explicit paths.
2026-03-13 13:53:03 +01:00
Andras Bacsai
b9cae51c5d feat(service): add container label escape control to services API
Add `is_container_label_escape_enabled` boolean field to services API,
allowing users to control whether special characters in container labels
are escaped. Defaults to true (escaping enabled).

When disabled, users can use environment variables within labels.
Includes validation rules and comprehensive test coverage.
2026-03-13 13:32:58 +01:00
Andras Bacsai
aac34f1d14 fix(git-import): explicitly specify ssh key and remove duplicate validation rules
- Add -i flag to explicitly specify ssh key path in git ls-remote operations
- Remove static $rules properties in favor of dynamic rules() method
- Fix test syntax error
2026-03-12 14:19:53 +01:00
Andras Bacsai
0991f8e2ca fix(application): clarify deployment type precedence logic
- Prioritize real private keys (id > 0) first
- Check source second before falling back to zero key
- Remove isDev() check that was restricting zero key behavior in dev
- Remove exception throw, use 'other' as safe fallback
- Expand test coverage to validate all precedence scenarios
2026-03-12 13:48:30 +01:00
Andras Bacsai
4f1fe824e5
fix(git-import): ensure ssh key is used for fetch, submodule, and lfs operations (#8933) 2026-03-12 13:35:26 +01:00
Andras Bacsai
92c8ad449f feat(git-import): support custom ssh command for fetch, submodule, and lfs
Allow passing a custom GIT_SSH_COMMAND to setGitImportSettings() so that git fetch,
submodule update, and lfs pull use the same SSH authentication as the initial clone.
This is required for git sources like GitLab that use custom ports and identity files.

Also remove unnecessary SSH retry event tracking and add test coverage.
2026-03-12 13:32:43 +01:00
Andras Bacsai
8b8a09ad39
fix(api): cast teamId to int in deployment authorization check (#8931) 2026-03-12 13:26:08 +01:00
Andras Bacsai
3819676555 fix(api): cast teamId to int in deployment authorization check
Ensure proper type comparison when verifying deployment team ownership.
Adds comprehensive feature tests for the GET /api/v1/deployments/{uuid} endpoint.
2026-03-12 13:25:10 +01:00
Andras Bacsai
8cb5e70167
fix(parsers): resolve shared variables in compose environment (#8930) 2026-03-12 13:24:48 +01:00
Andras Bacsai
7cfc6746c7 fix(parsers): resolve shared variables in compose environment
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.
2026-03-12 13:23:13 +01:00
Andras Bacsai
01031fc5f3 refactor: consolidate file path validation patterns and support scoped packages
- Extract file path validation regex into ValidationPatterns::FILE_PATH_PATTERN constant
- Add filePathRules() and filePathMessages() helper methods for reusable validation
- Extend allowed characters from [a-zA-Z0-9._\-/] to [a-zA-Z0-9._\-/~@+] to support:
  - Scoped npm packages (@org/package)
  - Language-specific directories (c++, rust+)
  - Version markers (v1~, build~)
- Replace duplicate inline regex patterns across multiple files
- Add tests for paths with @ symbol and tilde/plus characters
2026-03-12 13:09:13 +01:00
Andras Bacsai
709e5e882e Merge remote-tracking branch 'origin/next' into next 2026-03-11 18:16:15 +01:00
Andras Bacsai
54c5ad38da test(magic-variables): add feature tests for SERVICE_URL/FQDN variable handling
Add comprehensive test suite verifying that magic (referenced) SERVICE_URL_ and
SERVICE_FQDN_ variables don't overwrite values set by direct template declarations
or updateCompose(). Tests cover the fix for GitHub issue #8912 where generic
SERVICE_URL and SERVICE_FQDN variables remained stale after changing a service
domain in the UI. These tests ensure the transition from updateOrCreate() to
firstOrCreate() in the magic variables section works correctly.
2026-03-11 17:15:17 +01:00
Andras Bacsai
e52a49b5e9 feat(server): add server metadata collection and display
Add ability to gather and display server system information including OS, architecture, kernel version, CPU count, memory, and uptime. Includes:
- New gatherServerMetadata() method to collect system details via remote commands
- New refreshServerMetadata() Livewire action with authorization and error handling
- Server Details UI section showing collected metadata with refresh capability
- Database migration to add server_metadata JSON column
- Comprehensive test suite for metadata collection and persistence
2026-03-11 16:21:05 +01:00
Andras Bacsai
b2135bb4fa feat(gitlab): add GitLab source integration with SSH and HTTP basic auth
Add full GitLab application source support for git operations:
- Implement SSH-based authentication using private keys with configurable ports
- Support HTTP basic auth for HTTPS GitLab URLs (with or without deploy keys)
- Handle private key setup and SSH command configuration in both Docker and local modes
- Support merge request checkouts for GitLab with SSH authentication

Improvements to credential handling:
- URL-encode GitHub access tokens to handle special characters properly
- Update log sanitization to redact passwords from HTTPS/HTTP URLs
- Extend convertGitUrl() type hints to support GitlabApp sources

Add test coverage and seed data:
- New GitlabSourceCommandsTest with tests for private key and public repo scenarios
- Test for HTTPS basic auth password sanitization in logs
- Seed data for GitLab deploy key and public example applications
2026-03-11 15:30:46 +01:00
Andras Bacsai
108bae02d0
fix(livewire): add error handling and selectedActions to delete methods (#8909) 2026-03-11 15:05:53 +01:00
Andras Bacsai
8366e150b1 feat(livewire): add selectedActions parameter and error handling to delete methods
- Add `$selectedActions = []` parameter to delete/remove methods in multiple
  Livewire components to support optional deletion actions
- Return error message string when password verification fails instead of
  silent return
- Return `true` on successful deletion to indicate completion
- Handle selectedActions to set component properties for cascading deletions
  (delete_volumes, delete_networks, delete_configurations, docker_cleanup)
- Add test coverage for Danger component delete functionality with password
  validation and selected actions handling
2026-03-11 15:04:45 +01:00
Andras Bacsai
6488751fd2 feat(proxy): add database-backed config storage with disk backups
- Store proxy configuration in database as primary source for faster access
- Implement automatic timestamped backups when configuration changes
- Add backfill migration logic to recover configs from disk for legacy servers
- Simplify UI by removing loading states (config now readily available)
- Add comprehensive logging for debugging configuration generation and recovery
- Include unit tests for config recovery scenarios
2026-03-11 14:11:31 +01:00
Andras Bacsai
a7f491170a fix(deployment): filter null and empty environment variables from nixpacks plan
When application->fqdn is null, COOLIFY_FQDN and COOLIFY_URL are set to null.
These null values cause nixpacks to fail parsing the config with
"invalid type: null, expected a string".

Filter out null and empty string values when generating environment variables
for the nixpacks plan JSON. Fixes #6830.
2026-03-11 13:41:34 +01:00
Andras Bacsai
dcd976ae06 fix(git): ensure ssh credentials are propagated to submodule operations
- Add gitSshCommand parameter to setGitImportSettings and buildGitCheckoutCommand
- Extract hardcoded ssh commands to variables for consistency
- Apply custom ssh credentials to all git operations including submodule sync/update
- Configure git url rewriting for github token-based authentication with submodules
- Add comprehensive test suite for submodule credential propagation
2026-03-11 11:30:58 +01:00
Andras Bacsai
a596ff313e chore: prepare for PR 2026-03-11 07:04:33 +01:00
Andras Bacsai
5cac559602 chore: prepare for PR 2026-03-11 06:36:12 +01:00
Andras Bacsai
d174724bf6 Merge branch 'ghsa-mw5w-2vvh-mgf4-investigation' 2026-03-10 22:22:51 +01:00
Andras Bacsai
fcd574e1eb fix(log-drain): prevent command injection by base64-encoding environment variables
Replace direct shell interpolation of environment values with base64 encoding
to prevent command injection attacks. Environment configuration is now built as
a single string, base64-encoded, then decoded to file atomically.

Also add regex validation to restrict environment field values to safe
characters (alphanumeric, underscore, hyphen, dot) at the application layer.

Fixes GHSA-3xm2-hqg8-4m2p
2026-03-10 22:22:51 +01:00
Andras Bacsai
a1c30cb0e7 fix(git-ref-validation): prevent command injection via git references
Add validateGitRef() helper function that uses an allowlist approach to prevent
OS command injection through git commit SHAs, branch names, and tags. Only allows
alphanumeric characters, dots, hyphens, underscores, and slashes.

Changes include:
- Add validateGitRef() helper in bootstrap/helpers/shared.php
- Apply validation in Rollback component when accepting rollback commit
- Add regex validation to git commit SHA fields in Livewire components
- Apply regex validation to API rules for git_commit_sha
- Use escapeshellarg() in git log and git checkout commands
- Add comprehensive unit tests covering injection payloads

Addresses GHSA-mw5w-2vvh-mgf4
2026-03-10 22:22:48 +01:00
Andras Bacsai
096d4369e5 fix(sentinel): add token validation to prevent command injection
Add validation to ensure sentinel tokens contain only safe characters
(alphanumeric, dots, hyphens, underscores, plus, forward slash, equals),
preventing OS command injection vulnerabilities when tokens are
interpolated into shell commands.

- Add ServerSetting::isValidSentinelToken() validation method
- Validate tokens in StartSentinel action and metrics queries
- Improve shell argument escaping with escapeshellarg()
- Add comprehensive test coverage for token validation
2026-03-10 22:19:19 +01:00
Andras Bacsai
6fbb5e626a Squashed commit from '565g-9j4m-wqmr-cross-team-idor-logs-fix' 2026-03-10 22:11:52 +01:00
Andras Bacsai
c15bcd5634 fix(api): require write permission for validation endpoints
Validation operations should require write permissions as they trigger
state-changing actions. Updated middleware for:
- POST /api/v1/cloud-tokens/{uuid}/validate
- GET /api/v1/servers/{uuid}/validate

Added tests to verify read-only tokens cannot access these endpoints.
2026-03-10 22:11:52 +01:00
Andras Bacsai
0a1782175a Merge remote-tracking branch 'origin/next' into 8826-investigate-postgresql-restart 2026-03-10 21:46:03 +01:00
Andras Bacsai
d6ac8de6b7 Merge remote-tracking branch 'origin/next' into 8765-investigate-docker-cleanup-keep 2026-03-10 21:41:25 +01:00
Andras Bacsai
5c5f67f48b chore: prepare for PR 2026-03-10 20:37:22 +01:00
Andras Bacsai
e41dbde46b chore: prepare for PR 2026-03-10 18:34:37 +01:00
Andras Bacsai
9702543e20 chore: prepare for PR 2026-03-10 18:32:19 +01:00
Andras Bacsai
a362282976 chore: prepare for PR 2026-03-10 17:37:13 +01:00
Andras Bacsai
9b94ae1c1a Merge remote-tracking branch 'origin/next' into audit-policies 2026-03-10 10:52:39 +01:00
Andras Bacsai
27e2680d70 Merge remote-tracking branch 'origin/next' into fix/configurable-proxy-timeout 2026-03-10 10:01:46 +01:00
Andras Bacsai
184fbb98f3 fix(proxy): add validation and normalization for database proxy timeout
- Extract proxy timeout configuration logic into dedicated method
- Add min:1 validation rule for publicPortTimeout
- Normalize invalid timeout values (null, 0, negative) to default 3600s
- Add tests for timeout configuration normalization and validation
2026-03-10 09:59:19 +01:00
Andras Bacsai
e3daba0b1d chore: prepare for PR 2026-03-10 09:43:29 +01:00
Andras Bacsai
01aa534556 fix(application-source): support localhost key with id=0
Previously, the view checked $privateKeyId with ! operator, which
incorrectly treats 0 (localhost key) as falsy. Changed to explicit
is_null() checks to distinguish between null (no key) and 0 (localhost).
Added test coverage for both cases.
2026-03-09 17:20:33 +01:00
Andras Bacsai
4fa048f931 Merge remote-tracking branch 'origin/next' into audit-policies 2026-03-03 19:41:05 +01:00
Andras Bacsai
0ca5596b1f fix(server-limit): re-enable force-disabled servers at limit
Handle non-positive disable counts with `<= 0` so teams at or under the
server limit correctly re-enable force-disabled servers. Add a feature test
suite for ServerLimitCheckJob covering under-limit, at-limit, over-limit,
and no-op behavior.
2026-03-03 17:03:59 +01:00
Andras Bacsai
4f39cf6dc8 chore: prepare for PR 2026-03-03 16:43:29 +01:00
Andras Bacsai
d3b8d70f08 fix(subscription): harden quantity updates and proxy trust behavior
Centralize min/max server limits in Stripe quantity updates and wire them into
Livewire subscription actions with price preview/update handling.

Also improve host/proxy middleware behavior by trusting loopback hosts when FQDN
is set and auto-enabling secure session cookies for HTTPS requests behind
proxies when session.secure is unset.

Includes feature tests for loopback trust and secure cookie auto-detection.
2026-03-03 12:28:16 +01:00
Andras Bacsai
76ae720c36 feat(subscription): add Stripe server limit quantity adjustment flow
Introduce a new `UpdateSubscriptionQuantity` Stripe action to:
- preview prorated due-now and next-cycle recurring costs
- update subscription item quantity with proration invoicing
- revert quantity and void invoice when payment is not completed

Wire the flow into the Livewire subscription actions UI with a new adjust-limit modal,
price preview loading, and confirmation-based updates. Also refactor the subscription
management section layout and fix modal confirmation behavior for temporary 2FA bypass.

Add `Subscription::billingInterval()` helper and comprehensive Pest coverage for
quantity updates, preview calculations, failure/revert paths, and billing interval logic.
2026-03-03 12:24:13 +01:00
Andras Bacsai
09b169a222 Merge remote-tracking branch 'origin/next' into subscription-refunds-cancellation 2026-03-03 11:52:58 +01:00
Andras Bacsai
839635e9e8 chore: prepare for PR 2026-03-03 11:51:38 +01:00
Andras Bacsai
db6229f815 Merge remote-tracking branch 'origin/next' into subscription-refunds-cancellation 2026-03-03 10:40:30 +01:00
Andras Bacsai
2ad7df2dea Merge remote-tracking branch 'origin/next' into 8649-parseaddr-bug 2026-03-03 10:21:59 +01:00
Andras Bacsai
7ae76ebc79 test(factories): add missing model factories for app test suite
Enable `HasFactory` on `Environment`, `Project`, `ScheduledTask`, and
`StandaloneDocker`, and add dedicated factories for related models to
stabilize feature/unit tests.

Also bump `visus/cuid2` to `^6.0` and refresh `composer.lock` with the
resulting dependency updates.
2026-03-03 09:50:05 +01:00
Andras Bacsai
02858c0892 test(rollback): verify shell metacharacter escaping in git commit parameter 2026-03-03 09:05:01 +01:00
Andras Bacsai
2dc0597562 test(rollback): use full-length git commit SHA values in test fixtures
Update test data to use complete 40-character git commit SHA hashes instead of abbreviated 12-character values.
2026-03-02 13:31:48 +01:00
Andras Bacsai
862ab607b7 Merge remote-tracking branch 'origin/next' into fix/rollback-uses-correct-commit 2026-03-02 12:53:14 +01:00
Andras Bacsai
7154febf32 Merge remote-tracking branch 'origin/next' into audit-policies 2026-03-02 12:41:30 +01:00
Andras Bacsai
1234463fca feat(models): add is_required to EnvironmentVariable fillable array
Add is_required field to the EnvironmentVariable model's fillable
array to allow mass assignment. Include comprehensive tests to verify
all fillable fields are properly configured for mass assignment.
2026-03-02 12:34:30 +01:00
Andras Bacsai
059164224c fix(bootstrap): add bounds check to extractBalancedBraceContent
Return null when startPos exceeds string length to prevent out-of-bounds
access. Add comprehensive test coverage for environment variable parsing
edge cases.
2026-03-02 12:24:40 +01:00
Andras Bacsai
236745ede1 chore: prepare for PR 2026-03-01 18:49:40 +01:00
Andras Bacsai
43412a1a2a Merge remote-tracking branch 'origin/next' into subscription-refunds-cancellation 2026-03-01 14:39:34 +01:00
Andras Bacsai
816c455c69 Merge remote-tracking branch 'origin/next' into fix/rollback-uses-correct-commit 2026-03-01 14:39:26 +01:00
Andras Bacsai
9b7e2e15b0 Merge remote-tracking branch 'origin/next' into env-var-descriptions 2026-03-01 14:39:23 +01:00
Andras Bacsai
ad433a0798 Merge remote-tracking branch 'origin/next' into audit-policies 2026-03-01 13:03:51 +01:00
Andras Bacsai
31555f9e8a fix(jobs): prevent non-due jobs firing on restart and enrich skip logs with resource links
- Refactor shouldRunNow() to only fire on first run (empty cache) if actually due by cron schedule, preventing spurious executions after cache loss or service restart
- Add enrichSkipLogsWithLinks() method to fetch and populate resource names and links for tasks, backups, and docker cleanup jobs in skip logs
- Update skip logs UI to display resource column with links to related resources, improving navigation and context
- Add fallback display when linked resources are deleted
- Expand tests to cover both restart scenarios: non-due jobs (should not fire) and due jobs (should fire)
2026-02-28 18:03:29 +01:00
Andras Bacsai
63be5928ab feat(scheduler): add pagination to skipped jobs and filter manager start events
- Implement pagination for skipped jobs display with 20 items per page
- Add pagination controls (previous/next buttons) to the scheduled jobs view
- Exclude ScheduledJobManager "started" events from run logs, keeping only "completed" events
- Add ShouldBeEncrypted interface to ScheduledTaskJob for secure queue handling
- Update log filtering to fetch 500 recent skips and slice for pagination
- Use Log facade instead of fully qualified class name
2026-02-28 16:23:58 +01:00
Andras Bacsai
a0c177f6f2 feat(jobs): add queue delay resilience to scheduled job execution
Implement dedup key-based cron tracking to make scheduled jobs resilient to queue
delays. Even if a job is delayed by minutes, it will catch the missed cron window
by tracking previousRunDate in cache instead of relying on isDue() alone.

- Add dedupKey parameter to shouldRunNow() in ScheduledJobManager
  - When provided, uses getPreviousRunDate() + cache tracking for resilience
  - Falls back to isDue() for docker cleanups without dedup key
  - Prevents double-dispatch within same cron window

- Optimize ServerConnectionCheckJob dispatch
  - Skip SSH checks if Sentinel is healthy (enabled and live)
  - Reduces redundant checks when Sentinel heartbeat proves connectivity

- Remove hourly Sentinel update checks
  - Consolidate to daily CheckAndStartSentinelJob dispatch
  - Crash recovery handled by sentinelOutOfSync → ServerCheckJob flow

- Add logging for skipped database backups with context (backup_id, database_id, status)

- Refactor skip reason methods to accept server parameter, avoiding redundant queries

- Add comprehensive test suite for scheduling with various delay scenarios and timezones
2026-02-28 15:06:25 +01:00
Andras Bacsai
f68793ed69 feat(jobs): optimize async job dispatches and enhance Stripe subscription sync
Reduce unnecessary job queue pressure and improve subscription sync reliability:

- Cache ServerStorageCheckJob dispatch to only trigger on disk percentage changes
- Rate-limit ConnectProxyToNetworksJob to maximum once per 10 minutes
- Add progress callback support to SyncStripeSubscriptionsJob for UI feedback
- Implement bulk fetching of valid Stripe subscription IDs for efficiency
- Detect and report resubscribed users (same email, different customer ID)
- Fix CleanupUnreachableServers query operator (>= 3 instead of = 3)
- Improve empty subId validation in PushServerUpdateJob
- Optimize relationship access by using properties instead of query methods
- Add comprehensive test coverage for all optimizations
2026-02-28 13:18:44 +01:00
Andras Bacsai
d9e39ba211 Merge remote-tracking branch 'origin/next' into env-var-descriptions 2026-02-28 00:09:54 +01:00
Andras Bacsai
a565fc3b36 fix(rollback): escape commit SHA to prevent shell injection
Properly escape commit SHA using escapeshellarg() before passing it
to shell commands. Add comprehensive tests for git commit rollback
scenarios including shallow clone, fallback behavior, and HEAD handling.
2026-02-27 23:26:31 +01:00
Andras Bacsai
530037c213 Merge remote-tracking branch 'origin/next' into fix/rollback-uses-correct-commit 2026-02-27 23:24:08 +01:00
Andras Bacsai
66dc1515d4 fix(security): prevent snapshot replay in API token permission checks
Never trust Livewire component properties for authorization decisions, as
snapshots can be replayed from another user's session. Re-evaluate all
permission checks fresh using auth()->user()->can() against current policies
to ensure the authenticated user is being authorized, not a replayed copy.

- Replace cached canUse* booleans with fresh policy evaluation
- Add comprehensive security tests for token creation permissions
- Update API authorization tests to verify middleware blocking behavior
2026-02-27 22:58:44 +01:00
Andras Bacsai
c1cc7920e1 chore: prepare for PR 2026-02-27 18:31:35 +01:00
Andras Bacsai
b878dc8102 refactor(auth): enforce team member authorization across app
Restrict sensitive operations to admins/owners and hide sensitive data
from team members:
- Add authorization checks to Livewire components and API endpoints
- Restrict team members from accessing sensitive permissions and data
- Hide environment variable values from non-admin team members
- Update policies to enforce team-level admin status requirement
- Add useSensitivePermissions policy for read:sensitive tokens
- Improve disabled button UX with auth-specific tooltips
- Add authorization checks in middleware for API tokens

Closes authorization gaps in project management, server management,
and settings components.
2026-02-27 11:41:01 +01:00
Andras Bacsai
8f2800a9e5 chore: prepare for PR 2026-02-26 18:22:03 +01:00
Andras Bacsai
2b7e2ebafb chore: prepare for PR 2026-02-26 16:27:02 +01:00
Andras Bacsai
e82942b387 test: refresh api and job feature suites 2026-02-26 08:37:20 +01:00
Andras Bacsai
347af07a79 chore(tests): reorganize feature suites and expand team auth coverage 2026-02-26 07:13:19 +01:00
Andras Bacsai
34d8499a0c test(auth): cover authorization scenarios for api and ui 2026-02-26 06:55:08 +01:00
Andras Bacsai
52b88135f3 test(browser): improve "ResourceSettingsPersistence" assertions
Adjusted Discord notification setup, Livewire form submission handling, and checkbox interactions in `ResourceSettingsPersistenceTest` to better reflect page flows.
2026-02-25 22:35:37 +01:00
Andras Bacsai
9c1ca422ce test(browser): remove notification prompt helper 2026-02-25 19:28:39 +01:00
Andras Bacsai
37eac11df3 test(browser): cover resource settings persistence 2026-02-25 19:26:55 +01:00
Andras Bacsai
f09bbb4a04 Merge remote-tracking branch 'origin/next' into audit-policies
# Conflicts:
#	tests/Unit/Policies/GithubAppPolicyTest.php
#	tests/Unit/Policies/SharedEnvironmentVariablePolicyTest.php
2026-02-25 18:53:39 +01:00
Andras Bacsai
ede75283db test(browser): expand server/project auth coverage 2026-02-25 18:50:26 +01:00
Andras Bacsai
94dfd6a54e fix(auth): enforce authorization checks in Livewire components
- Replace manual ownership checks with authorize() in Destination/Show, NavbarDeleteTeam, and Project/Show
- Add authorization checks for team deletion and environment creation
- Add proper exception handling with try-catch blocks
- Add comprehensive feature and browser tests for authorization scenarios
- Update CLAUDE.md with Pest Browser Plugin testing guidelines
2026-02-25 16:38:04 +01:00
Andras Bacsai
41e1248b6f fix(auth): enforce proxy authorization checks in server navbar
Add authorization gate using @can('manageProxy') directive to ensure only
authorized users can view and interact with proxy control buttons (restart,
stop, start) in the server navbar component. Refactor tests to validate that
members cannot see proxy buttons while admins can.
2026-02-25 15:37:04 +01:00
Andras Bacsai
fcc58ca08a fix(auth): enforce dashboard authorization and improve team deletion
Add authorization gates to Project and Server creation buttons in the dashboard to prevent non-admin users from accessing resource creation. Improve team deletion to clear cache before deletion and automatically switch to the user's next available team.

- Hide create buttons from non-admin users in dashboard
- Clear cache before team deletion to prevent stale session resolution
- Switch user session to next available team when current team is deleted
- Handle refreshSession when user has no remaining teams
- Add tests for dashboard authorization enforcement and team deletion flow
2026-02-25 14:47:35 +01:00
Andras Bacsai
86b05b902a fix(auth): enforce authorization checks across API and Livewire components
- Add authorization checks to API controller endpoints (view, create, update, delete)
- Wrap Livewire component methods with try-catch for consistent error handling
- Add AuthorizesRequests trait to components requiring authorization checks
- Ensure all sensitive operations verify user permissions before execution
- Implement unified error handling with handleError() helper function
2026-02-25 14:20:29 +01:00
Aditya Tripathi
b71ad865dc feat: refresh private repository if updating 2026-02-25 11:39:43 +00:00
Andras Bacsai
c93296e9a6
feat(healthcheck): add command-based health check support (#8612) 2026-02-25 12:09:59 +01:00
Andras Bacsai
b88f9fca67 chore: prepare for PR 2026-02-25 12:07:29 +01:00
Andras Bacsai
fe36b70680 chore: prepare for PR 2026-02-25 12:00:24 +01:00
Andras Bacsai
521d995ea1 Merge remote-tracking branch 'origin/next' into 7765-healthcheck-investigation 2026-02-25 11:57:58 +01:00
Andras Bacsai
8e2f0836da chore: prepare for PR 2026-02-25 11:52:18 +01:00
Andras Bacsai
57848c25e9
fix(docker): centralize command escaping in executeInDocker helper (#8615) 2026-02-25 11:51:23 +01:00
Andras Bacsai
992b922df3 chore: prepare for PR 2026-02-25 11:50:57 +01:00
Andras Bacsai
0580af0d34 feat(healthchecks): add command health checks with input validation
Add support for command-based health checks in addition to HTTP-based checks:
- New health_check_type field supporting 'http' and 'cmd' values
- New health_check_command field with strict regex validation
- Updated allowedFields in create_application and update_by_uuid endpoints
- Validation rules include max 1000 characters and safe character whitelist
- Added feature tests for health check API endpoints
- Added unit tests for GithubAppPolicy and SharedEnvironmentVariablePolicy
2026-02-25 11:38:09 +01:00
Andras Bacsai
609cb4190e fix(health-checks): sanitize and validate CMD healthcheck commands
- Add regex validation to restrict allowed characters (alphanumeric, spaces, and specific safe symbols)
- Enforce maximum 1000 character limit on healthcheck commands
- Strip newlines and carriage returns to prevent command injection
- Change input field from textarea to text input in UI
- Add warning callout about prohibited shell operators
- Add comprehensive validation tests for both valid and malicious command patterns
2026-02-25 11:28:33 +01:00
Andras Bacsai
24abd51238
fix(auth): prevent cross-tenant IDOR in resource cloning (#8613) 2026-02-25 11:21:52 +01:00
Andras Bacsai
1759a1631c chore: prepare for PR 2026-02-25 11:18:46 +01:00
Andras Bacsai
30c0b37689 chore: prepare for PR 2026-02-25 10:58:29 +01:00
Andras Bacsai
d8419fad93 chore: prepare for PR 2026-02-24 14:57:32 +01:00
Tjeerd Smid
175e5b3c6d
Merge branch 'next' into fix/rollback-uses-correct-commit 2026-02-24 13:18:46 +01:00
Andras Bacsai
2986d7604e chore: prepare for PR 2026-02-24 10:17:16 +01:00
Tjeerd Smid
1935403053 fix: application rollback uses correct commit sha
- setGitImportSettings() now accepts optional $commit parameter
 - Uses passed commit over application's git_commit_sha (typically HEAD)
 - Fixes rollback deploying latest instead of selected commit
 - Also fixes shallow clone "bad object" error on rollback

Fixes #8445
2026-02-23 20:13:07 +01:00
Andras Bacsai
ec14b55f0a chore: prepare for PR 2026-02-23 14:28:28 +01:00
Andras Bacsai
620da191b1 chore: prepare for PR 2026-02-23 14:15:13 +01:00
Andras Bacsai
1f3fca5f71
fix(database): chown redis/keydb configs when custom conf set (#8561) 2026-02-23 13:26:58 +01:00
Andras Bacsai
76a6960f44 chore: prepare for PR 2026-02-23 13:26:01 +01:00
Andras Bacsai
133241bac1
fix(service): resolve team lookup via service relationship (#8559) 2026-02-23 13:24:01 +01:00
Andras Bacsai
61a54afe2b fix(service): resolve team lookup via service relationship
Update service application/database team accessors to traverse the service relation chain and add coverage to prevent null team regressions.
2026-02-23 13:23:12 +01:00
Andras Bacsai
bf51ed905f chore: prepare for PR 2026-02-23 13:02:06 +01:00
Andras Bacsai
73170fdd33 chore: prepare for PR 2026-02-23 12:12:10 +01:00
Andras Bacsai
fd24a54304
feat(monitoring): add scheduled job monitoring dashboard (#8433) 2026-02-18 16:16:56 +01:00
Andras Bacsai
664b31212f chore: prepare for PR 2026-02-18 15:42:42 +01:00
Andras Bacsai
ab79a51e29 fix(api): improve scheduled tasks API with auth, validation, and execution endpoints
- Add authorization checks ($this->authorize) for all read/write operations
- Use customApiValidator() instead of Validator::make() to match codebase patterns
- Add extra field rejection to prevent mass assignment
- Use Application::ownedByCurrentTeamAPI() for consistent query patterns
- Remove non-existent standalone_postgresql_id from hidden fields
- Add execution listing endpoints for both applications and services
- Add ScheduledTaskExecution OpenAPI schema
- Use $request->only() instead of $request->all() for safe updates
- Add ScheduledTaskFactory and feature tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 11:53:58 +01:00
Andras Bacsai
1519666d4c chore: prepare for PR 2026-02-15 14:14:23 +01:00
Andras Bacsai
b40926e915 chore: prepare for PR 2026-02-15 14:14:23 +01:00
Andras Bacsai
76a770911c fix(server): improve IP uniqueness validation with team-specific error messages
- Refactor server IP duplicate detection to use `first()` instead of `get()->count()`
- Add team-scoped validation to distinguish between same-team and cross-team IP conflicts
- Update error messages to clarify ownership: "already exists in your team" vs "in use by another team"
- Apply consistent validation logic across API, boarding, and server management flows
- Add comprehensive test suite for IP uniqueness enforcement across teams
2026-02-15 14:14:23 +01:00
Andras Bacsai
6dea1ab0f3 test: add dashboard test and improve browser test coverage
- Add DashboardTest with tests for project/server visibility
- Add screenshots to existing browser tests for debugging
- Skip onboarding in dev mode for faster testing
- Update gitignore to exclude screenshot directories
2026-02-11 16:37:40 +01:00
Andras Bacsai
47a3f2e2cd test: add Pest browser testing with SQLite :memory: schema
Set up end-to-end browser testing using Pest Browser Plugin + Playwright.
New v4 test suite uses SQLite :memory: database with pre-generated schema dump
(database/schema/testing-schema.sql) instead of running migrations, enabling
faster test startup.

- Add pestphp/pest-plugin-browser dependency
- Create GenerateTestingSchema command to export PostgreSQL schema to SQLite
- Add .env.testing configuration for isolated test environment
- Implement v4 test directory structure (Feature, Browser, Unit tests)
- Update Pest skill documentation with browser testing patterns, API reference,
  debugging techniques, and common pitfalls
- Configure phpunit.xml and tests/Pest.php for v4 suite
- Update package.json and docker-compose.dev.yml for testing dependencies
2026-02-11 15:25:47 +01:00
Andras Bacsai
95e93ad899 chore: prepare for PR 2026-02-09 14:48:16 +01:00
Andras Bacsai
c0dadc003d fix(env): skip escaping for valid JSON in environment variables (#6160)
Prevent double-escaping of COMPOSER_AUTH and other JSON environment variables
by detecting valid JSON objects/arrays in realValue() and skipping quote
escaping entirely. This fixes broken JSON values passed to runtime services
while maintaining proper escaping for non-JSON values.

- Add JSON detection before escaping logic in EnvironmentVariable::realValue()
- JSON objects/arrays pass through unmodified, avoiding quote corruption
- Add comprehensive test coverage for JSON vs non-JSON escaping behavior
2026-01-28 10:59:00 +01:00
Andras Bacsai
95091e918f fix: optimize queries and caching for projects and environments 2026-01-16 11:51:26 +01:00
Andras Bacsai
a8aa452475 fix: prevent metric charts from freezing when navigating with wire:navigate
Wraps inline chart initialization scripts in IIFEs to create local scope for variables. This prevents "Identifier has already been declared" errors when Livewire's SPA navigation re-executes scripts, allowing smooth navigation between metrics pages without page refresh.

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

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-01-02 12:36:17 +01:00
Andras Bacsai
0e9dbc3625 fix(metrics): address code review feedback for LTTB downsampling
- Wrap return values in collect() to maintain Collection compatibility
- Add comment explaining threshold <= 2 prevents division by zero
- Refactor tests to use actual Server model method via reflection
- Use seeded mt_rand() for reproducible test results

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 13:39:43 +01:00
Andras Bacsai
f199b6bfc4 fix(metrics): prevent page freeze with 30-day server metrics interval using LTTB downsampling
Implement the Largest-Triangle-Three-Buckets (LTTB) algorithm to downsample
metrics data for large time intervals (30 days generates 260K-500K+ points).
Reduces rendered points to ~1000 while preserving visual accuracy of peaks
and valleys. Fixes unresponsive page when selecting 30-day metrics interval.

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

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-27 19:10:02 +01:00
Andras Bacsai
208f0eac99 feat: add comprehensive environment variable parsing with nested resolution and hardcoded variable detection
This commit introduces advanced environment variable handling capabilities including:
- Nested environment variable resolution with circular dependency detection
- Extraction of hardcoded environment variables from docker-compose.yml
- New ShowHardcoded Livewire component for displaying detected variables
- Enhanced UI for better environment variable management

The changes improve the user experience by automatically detecting and displaying
environment variables that are hardcoded in docker-compose files, allowing users
to override them if needed. The nested variable resolution ensures complex variable
dependencies are properly handled.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-27 15:24:53 +01:00
Andras Bacsai
d67fcd1dff feat: add magic variable detection and update UI behavior accordingly 2025-12-27 15:24:09 +01:00
Andras Bacsai
89192c9862 feat: add function to extract inline comments from docker-compose YAML environment variables 2025-12-27 15:24:09 +01:00
Andras Bacsai
e4cc5c1178 fix: update success message logic to only show when changes are made 2025-12-27 15:24:09 +01:00
Andras Bacsai
d640911bb9 fix: preserve existing comments in bulk update and always show save notification
This commit fixes two UX issues with environment variable bulk updates:

1. Comment Preservation (High Priority Bug):
   - When bulk updating environment variables via Developer view, existing
     manually-entered comments are now preserved when no inline comment is provided
   - Only overwrites existing comments when an inline comment (#comment) is explicitly
     provided in the pasted content
   - Previously: pasting "KEY=value" would erase existing comment to null
   - Now: pasting "KEY=value" preserves existing comment, "KEY=value #new" overwrites it

2. Save Notification (UX Improvement):
   - "Save all Environment variables" button now always shows success notification
   - Previously: only showed notification when changes were detected
   - Now: provides feedback even when no changes were made
   - Consistent with other save operations in the codebase

Changes:
- Modified updateOrCreateVariables() to only update comment field when inline comment
  is provided (null check prevents overwriting existing comments)
- Modified handleBulkSubmit() to always dispatch success notification unless error occurred
- Added comprehensive test coverage for bulk update comment preservation scenarios

Tests:
- Added 4 new feature tests covering comment preservation edge cases
- All 22 existing unit tests for parseEnvFormatToArray pass
- Code formatted with Pint

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-27 15:24:09 +01:00
Andras Bacsai
2bba5ddb2e refactor: add explicit fillable array to EnvironmentVariable model
Replace permissive $guarded = [] with explicit $fillable array for better security and clarity. The fillable array includes all 13 fields that are legitimately mass-assignable:

- Core: key, value, comment
- Polymorphic relationship: resourceable_type, resourceable_id
- Boolean flags: is_preview, is_multiline, is_literal, is_runtime, is_buildtime, is_shown_once, is_shared
- Metadata: version, order

Also adds comprehensive test suite (EnvironmentVariableMassAssignmentTest) with 12 test cases covering:
- Mass assignment of all fillable fields
- Comment field edge cases (null, empty, long text)
- Value encryption verification
- Key mutation (trim and space replacement)
- Protection of auto-managed fields (id, uuid, timestamps)
- Update method compatibility

All tests passing (12 passed, 33 assertions).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-27 15:24:09 +01:00
Andras Bacsai
ab472bf5ed feat: enhance environment variable handling to support mixed formats and add comprehensive tests 2025-12-27 15:24:09 +01:00
Andras Bacsai
201c9fada3 feat: limit comment field to 256 characters for environment variables 2025-12-27 15:24:09 +01:00
Andras Bacsai
e33558488e feat: add comment field to environment variables
- Add comment field to EnvironmentVariable model and database
- Update parseEnvFormatToArray to extract inline comments from env files
- Update Livewire components to handle comment field
- Add UI for displaying and editing comments
- Add tests for comment parsing functionality
2025-12-27 15:24:09 +01:00
Andras Bacsai
582bdc3739 test: Add comprehensive preview deployment port and path tests
Add missing edge case test for root path (/) and expand test coverage
for preview FQDN generation. Tests verify that ports and paths are
correctly preserved in preview URLs while excluding root paths.

Fixes #2184
2025-12-17 21:35:54 +01:00
Andras Bacsai
5e3593e8bf Enhance log sanitization with GitHub, GitLab, AWS, and generic URL passwords
Consolidate all PII/secret sanitization into remove_iip() to protect real-time logs in addition to exported logs. Add detection for GitHub tokens (ghp_, gho_, ghu_, ghs_, ghr_), GitLab tokens (glpat-, glcbt-, glrt-), AWS credentials (AKIA/ABIA/ACCA/ASIA access keys and secret keys), and generic URL passwords for FTP, SSH, AMQP, LDAP, and S3 protocols.

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

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-17 17:59:10 +01:00
Andras Bacsai
96f2e81191
feat: copy resource logs with PII/secret sanitization (#7648) 2025-12-17 16:05:13 +01:00
Andras Bacsai
d4a403278d
Added ClickHouse Migration Support (#7392) 2025-12-17 11:37:53 +01:00
Duane Adam
b0b3098abe
Merge branch 'next' into feat/copy-resource-logs-with-sanitization 2025-12-16 12:03:53 +08:00
Duane Adam
327e8181af
Add copy logs button with PII/secret sanitization
Add a copy button to individual container logs that strips sensitive
data before copying to clipboard. Includes sanitization for emails,
database URLs with passwords, JWT tokens, API keys, private key blocks,
and git access tokens.
2025-12-16 11:49:40 +08:00
Andras Bacsai
67b1db9254 feat: add Hetzner Cloud server linking for manually-added servers
Allow manually-added servers to be linked to Hetzner Cloud instances by
matching IP address. Once linked, servers gain power controls and status
monitoring.

Changes:
- Add getServers() and findServerByIp() methods to HetznerService
- Add Hetzner linking UI section to Server General page
- Add unit tests for new HetznerService methods

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 22:14:41 +01:00
Andras Bacsai
98b99cbb09
Fix read-only volume detection and add refresh capability (#7588) 2025-12-11 21:41:36 +01:00
Andras Bacsai
f152ec00ad fix: Detect read-only Docker volumes with long-form syntax and enable 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 <noreply@anthropic.com>
2025-12-11 14:18:58 +01:00
Andras Bacsai
6ea563c6ac Fix: Prevent coolify-helper and coolify-realtime images from being pruned
Current version of infrastructure images (coolify-helper, coolify-realtime) are now protected from deletion during docker cleanup, regardless of which registry they're pulled from (ghcr.io, docker.io, or Docker Hub implicit). Old versions continue to be cleaned up as intended.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-11 13:38:52 +01:00
Andras Bacsai
5d38147899 feat(api): Improve OpenAPI spec and add rate limit handling for Hetzner
- Add 429 response with Retry-After header for Hetzner server creation
- Create RateLimitException for proper rate limit error handling
- Rename cloud_provider_token_id to cloud_provider_token_uuid with deprecation
- Fix prices array schema in server-types endpoint with proper items definition
- Add explicit default: true to autogenerate_domain properties
- Add timeout and retry options to Docker install curl commands
- Fix race condition in deployment status update using atomic query
2025-12-11 12:12:43 +01:00
Andras Bacsai
a5331db179 Fix: Correctly set session for team before creating user token 2025-12-11 11:59:59 +01:00