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.
- 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>
- 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>
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Replaces Model::forceCreate([...]) calls with (new Model)->forceFill([...])->save()
across SettingsBackup, Server, and User models to avoid bypassing Eloquent
model event lifecycle during record creation.
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.
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.
Use `$this->mainServer` when resolving environment variable values across
deployment env generation (runtime, buildtime, nixpacks, args, and secrets
hash) so shared server-scoped values are applied consistently.
Also add `server_id` to `SharedEnvironmentVariable::$fillable` and normalize
the Livewire Blade file newline.
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.
Update property access in database components and Application model to
use snake_case conventions (common_name, subject_alternative_names)
for Eloquent attributes. Also add null-safe operators (?->) for
settings access in Application model to handle null values safely.