fix(server-transfer): harden import on Cloud and stop archives from using server slots

- Rate limit the import check probe and refuse private, loopback, and
  link-local targets on Cloud.
- Rate limit the SSH validation that an import starts, like other
  server validations.
- Count only managed servers for the server limit, the limit check job,
  and the subscription page. Archives of transferred servers are left out.
- Do not show the name of another team's archived server in the import check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai
2026-10-23 20:12:59 +02:00
co-authored by Claude Opus 5.5
parent 30d840f1c6
commit 95a3a22fdf
9 changed files with 106 additions and 9 deletions
+20
View File
@@ -81,3 +81,23 @@ it('does not change servers when under limit and none are force-disabled', funct
expect($server1->fresh()->settings->force_disabled)->toBeFalsy();
expect($server2->fresh()->settings->force_disabled)->toBeFalsy();
});
it('does not count archives of transferred servers against the limit', function () {
$this->team->update(['custom_server_limit' => 1]);
$live = createServerForTeam($this->team);
sleep(1);
$archive = createServerForTeam($this->team);
$archive->forceFill(['server_metadata' => ['transfer' => ['status' => 'transferred']]])->save();
ServerLimitCheckJob::dispatchSync($this->team);
expect($live->fresh()->settings->force_disabled)->toBeFalsy()
->and(Team::serverLimitReached($this->team))->toBeTrue()
->and($this->team->serverOverflow())->toBeFalse();
Notification::assertNothingSent();
$live->forceFill(['server_metadata' => ['transfer' => ['status' => 'transferred']]])->save();
expect(Team::serverLimitReached($this->team))->toBeFalse();
});