Wrap first-use SSH and SCP multiplexed commands with a lock to avoid racing while the control socket is created. Also detect native OpenSSH mux master process names during stale connection cleanup and cover both orphaned and duplicate mux processes with tests.
Remove explicit SSH master pre-warming and lock handling so OpenSSH manages ControlMaster creation lazily from real ssh/scp commands. Add cleanup for duplicate mux processes and update coverage around mux command options and stale process cleanup.
Serialize multiplexed SSH master creation per server to avoid concurrent workers spawning orphaned processes. Enable scheduled cleanup for stale mux connections and add guarded orphan process reaping with tests.
- resolve the GitHub App by a stable identifier during installation
callbacks so installing and re-installing keeps working over the
full lifetime of the App
- verify the installation id received from the callback against the
GitHub API before persisting it
- support re-installing an already configured GitHub App instead of
blocking it
- require an authenticated session and rate limit the setup callback
routes
- extend manifest setup state validity to match GitHub's manifest
code lifetime
Adds feature coverage for the GitHub App setup and installation
callbacks.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Centralize scheduled job queue selection with crons_queue() and use it for scheduler, task, and database backup jobs so cloud runs on crons while self-hosted stays on high.
Use config-based queue selection for deployment and scheduled jobs so cloud dispatches deployments to `deployments` and scheduled jobs to `crons`, while self-hosted keeps using `high`.
Add coverage for deployment queue helper, start action routing, and scheduled job manager routing.
Git hosts treat owner/repo names case-insensitively, but the exact
repository match used a case-sensitive comparison, so a payload whose
casing differed from the stored git remote would fail to match and
skip a legitimate deployment.
Lowercase both canonical repository paths before comparing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The manual webhook handlers selected target applications with a
`git_repository LIKE %full_name%` substring query, so a payload
repository name could match unintended applications when repository
names overlap.
Add a `MatchesManualWebhookApplications` trait that validates the
incoming `owner/repo` value and matches `Application.git_repository`
by exact normalized path. Github, Gitlab, Gitea and Bitbucket manual
handlers now use it, reject invalid repository input early, and return
a consistent generic webhook failure payload.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolve the server and network in Destination::addServer() and
::promote() through ownedByCurrentTeam() before use, authorize the
update against the resource, and pass the validated IDs into
attach()/detach()/update(). Errors are routed through handleError()
to match the sibling removeServer() method.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move Sentinel push handling into a controller and dispatch server update jobs only when container state changes or the force interval elapses. Add opt-in PostgreSQL read/write replica configuration and tune periodic proxy network and storage checks to reduce unnecessary work.
Add feature coverage for replica config, Sentinel push deduplication, deployment log scrolling, and server update job optimizations.
Scope DeleteEnvironment::mount() and delete() lookups through
Environment::ownedByCurrentTeam() so an environment_id that belongs to
another team resolves to a 404 instead of loading the foreign record.
Mark $environment_id as #[Locked] so the public Livewire property can no
longer be reassigned from the client.
Add tests/Feature/DeleteEnvironmentTeamScopingTest.php covering mount,
delete, the #[Locked] guard, and the team-scoped helper for both the
cross-team and own-team cases.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Source component now resolves the supplied private key and Git
source IDs through team-scoped queries before persisting them, so a
selection can only ever reference a resource owned by the current
team. The source type is additionally restricted to the supported
GitHub/GitLab app classes.
The privateKeyId property is marked #[Locked] so it can only change
through the dedicated handler rather than a direct property update.
Adds feature tests covering team-scoped selection of private keys and
Git sources.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Clickhouse, Dragonfly, and Keydb still called syncData() inside the
DatabaseProxyStopped broadcast handler, clobbering in-progress edits to
name/description/credentials. Refresh only is_public/public_port/
public_port_timeout instead, matching the pattern used elsewhere.
Also null-guard HasDatabaseStatusInfo::getListeners() against an absent
Auth::user()/currentTeam(), add explicit return types on getListeners()
and render(), and convert inline comments in the SSL refresh test to a
PHPDoc block.
The earlier refreshStatus fix kept user-typed values intact but Livewire still
absorbed deferred wire:model values into the snapshot on every broadcast-
triggered roundtrip, clearing the unsaved-changes indicator and making the form
look auto-saved. Move all status-derived display (DB URLs, SSL toggle/mode,
cert expiry) out of each DB General form into a sibling StatusInfo Livewire
component, so the form never roundtrips on broadcasts.
Shared scaffolding lives in App\Traits\HasDatabaseStatusInfo plus an x-database-
status-info Blade component, leaving each per-DB StatusInfo class as a ~20-50
line declaration of label, SSL mode options, and SSL save hooks. Parents
dispatch databaseUpdated from save methods so the sibling refreshes after writes.
Tests cover the architecture (no DB form subscribes to status broadcasts) and
the sibling's refresh-on-status-change behavior.
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.
Call the preview environment variable relationship as a query when building the legacy configuration hash, and cover preview deployments with a regression test.
Dispatch configuration change events after saving application source and advanced settings, and refresh the configuration checker before showing redeploy 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.
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.
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.
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.
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.
Avoid failing Stripe webhook processing when local subscriptions are missing, and cover ignored invoice/payment/subscription events with feature tests.
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.
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.
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.
- `/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)