Hold a cache lock keyed by database UUID across the active-import
check and remote_process so two concurrent requests cannot both
queue a restore against the same database.
ConfigureDnsRecordJob requires a string content value. Guard
configureDnsAfterDomainAdd with the same blank and FILTER_VALIDATE_IP
checks used by createManagedDnsRecord so a missing or hostname-only
server address cannot TypeError after the domain is saved.
PostgreSQL single-database restores no longer always replace existing
objects. Update the file and S3 confirmation dialogs so they match the
callout instead of claiming all data will be replaced.
Allow single-database PostgreSQL imports to drop matching objects before restore. The API and import form accept replace_existing, which adds --clean --if-exists to pg_restore, and pg_restore now uses --exit-on-error.
Remove the enable/disable toggle from the server UI, logs page, and
Sentinel API so is_sentinel_enabled is derived and read-only. Enable
existing regular servers via migration, start Sentinel after validate-
and-install, and drop the daily ServerManagerJob restart.
Replace the collapsible mobile configuration menu with an always-visible
responsive grid, stack the mobile heading, and swap the domain editor
unsaved bar for a sticky Save footer with a scrollable form body.
Centralize scp-style Git URL parsing so user@host:path (including custom
usernames and embedded ports) is accepted and converted to HTTPS for
public clones, API create, webhooks, validation, and commit/branch links.
Use resolveStoredTeam() instead of teams()->first() when picking the
next active team after a team deletion or when an admin switches into
a user's account, so a valid stored preference wins over an arbitrary
first team. DeleteTeam now returns null when the deletion leaves the
owner with multiple teams, deferring to the selection screen instead
of guessing. refreshSession also stops persisting current_team_id
while impersonating, so viewing another user's account no longer
overwrites their real last-active team.
Make clearStoredTeamIfMatches perform an atomic conditional UPDATE
so a concurrent team switch isn't clobbered, and call it for the
deleting owner in DeleteTeam so their stored team id doesn't point
at a deleted team. refreshSession now falls back to
resolveStoredTeam() instead of an arbitrary first team. Add a
return type to SelectTeam::render() and tests covering owner
deletion and concurrent-selection preservation.
Reset the user's persisted current_team_id when they are removed from
a team, when their team is deleted, or when refreshSession finds no
team left, so a dangling reference is never restored on next login.
Add current_team_id to users so the last active team is restored on
login instead of always defaulting to the personal team. When a user
belongs to multiple teams and has no valid stored choice, redirect
them to a new team.select screen (SelectTeam Livewire component) to
pick one, rather than silently choosing the first team. Update
Fortify and OAuth login flows to use the new resolveStoredTeam()
logic.
Switch analytics overview cards and skeleton tiles from white/base
backgrounds to --coollabs-base, show metric labels on skeletons, and
replace the scaled chevron-down path with a 24px polyline. Update
feature tests for the new tile classes and icon.
Add a light/dark ring around the dashboard analytics KPI group and use canvas-tinted dark card backgrounds instead of dark:bg-base so the cards match other dashboard surfaces.
Add a per-server Analytics page scoped to that host, move traffic
settings out of Sentinel, and put metrics settings on Charts.
Surface 4xx/5xx on path rows and restyle deployment logs.
Chart tooltips now list the viewer's local time and UTC with short
timezone names, instead of a UTC-only stamp. Also add a little left
padding on the traffic requests chart so axis labels are not clipped.
Pass series bucket timestamps to sparkline payloads so charts align with the selected range. Show loading overlays on analytics filters and range tabs, restyle the analytics header, and replace Sentinel custom-image autosave with an Apply and restart button so the unsaved bar no longer flashes.
The metrics-disabled empty state already titles itself "Metrics are disabled", so the extra status badge was redundant. Cover the Sentinel-enabled branch so that badge does not return.
Move the settings-section body class onto each domain group so apps
render as stacked cards instead of a single bordered list. Update the
ServiceDomains view assertions to match.
Standard buttons now capitalize each word in their labels. Movement and
depth-shadow changes use an 80ms duration while color transitions stay
at 120ms.
Neutral buttons in dark mode now use a white 8% depth edge so it matches
the regular border. Highlighted buttons keep the accent-mixed edge.
Document the behavior and assert the dark-mode selector in CSS tests.
Standard .button controls now use a compact 2px bottom edge, lift 1px on
hover, and press down with the depth removed. Highlighted buttons mix the
accent with black for a matching edge, and focus-visible keeps the accent
ring. Other button-like controls still use the lighter scale press.
Scroll active application settings sections with buttons instead of Livewire navigation, persist sidebar collapse even with auto-collapse, drop the unused modal id, and right-align destination status.
Introduce theme-controls and theme-controls/picker Blade components
housing the theme/page-width/custom-color logic previously duplicated
in top-user-menu and profile/appearance, and fix custom theme surface
colors to use oklch mixes instead of raw white/black/hex for correct
contrast.
Use the Coolify data volume path in local env so Sentinel can read access.log instead of the production proxy path. Cover the directory and TRAFFIC_ACCESS_LOG_PATH in tests.
Show routing summaries on domain tables below 600px instead of squeezing desktop columns. Scope preview add/edit Livewire events by preview id, authorize preview domain actions, and add search plus unsaved-edit handling.
Preserve in-progress domain edits and redirects across Livewire
refreshes, copy www port overrides for service redirect pairs, and
relocate preview deployment toggles from Advanced to Previews.
Unsaved bars can stay dirty via Alpine while a modal is closed, and
service domain tables stack at narrow widths.
Unify service backup history with pagination, schedule settings actions, S3 destination details, and team-safe access checks. Display server built-ins as read-only variables and add loading and empty states for searchable resources.