fix(core,admin-template): GC 스케줄 허용목록 동기 + 스토리지 잔존물 GC 신설 + 스케줄 모달 저장 회귀 수정
공개 후속 전수 조사의 실작업: - attachments:prune-orphans 관리자 예약 허용목록 등재 + 가드 테스트 도출 규칙을 런타임 validator 와 일치 (옵션 포함 키는 영원히 매칭되지 않는 죽은 항목) - layout-previews:cleanup 을 gc-schedules 가드 구간으로 편입 (+onOneServer) - storage:prune-leftovers 신설: 중단된 업데이트/설치의 _pending 스테이징·코어 임시· vendor 스테이징(3일)과 오래된 백업(30일, 최신 1개 상시 보존), 레거시 browser.log 회수 — 산출물 누적 + 회수 경로 부재( 동형) 7건 해소 - 언어팩 설치 임시 디렉토리 정리를 finally 로 이동 (설치 성공 시 100% 누수) - 브라우저 콘솔 로그를 daily(7일) 로테이션으로 전환 (단일 파일 989MB 실측) - 검수 중 발견한 스케줄 등록/수정 모달 저장 불능 수정 (Form id 부재 + 커스텀 Select/Toggle 값 미전송) + 동형 재발 차단 audit 룰 2종 신설
This commit is contained in:
1 parent
db49e8b9b8
commit
febffb173e
21 files changed
+1185
-29
No files matched your search
@@ -13,6 +13,7 @@ use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
@@ -768,6 +769,51 @@ class LanguagePackServiceTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* URL 설치가 성공해도 다운로드 임시 디렉토리(storage/app/temp/{uuid})가 남지 않는다.
|
||||
*
|
||||
* 임시 디렉토리 삭제가 catch 경로에만 있으면 실패 시에는 정리되고 성공 시에는
|
||||
* 100% 잔존한다 — 예외도 로그도 없이 설치할 때마다 ZIP 사본이 쌓이는 누수다.
|
||||
* 성공 경로를 실제로 통과시켜 잔존물이 0건임을 고정한다.
|
||||
*
|
||||
* @scenario vector=install_from_url, actor_permission=cli_system
|
||||
*
|
||||
* @effects successful_install_leaves_no_temp_directory
|
||||
*/
|
||||
public function test_install_from_url_success_leaves_no_temp_directory(): void
|
||||
{
|
||||
$identifier = 'tmpleak-core-ja';
|
||||
$zipPath = tempnam(sys_get_temp_dir(), 'lp_zip');
|
||||
$zip = new \ZipArchive;
|
||||
$zip->open($zipPath, \ZipArchive::OVERWRITE);
|
||||
$zip->addFromString(
|
||||
'language-pack.json',
|
||||
(string) json_encode($this->coreJaManifest($identifier, 'tmpleak', '1.0.0'), JSON_UNESCAPED_UNICODE)
|
||||
);
|
||||
$zip->close();
|
||||
|
||||
Http::fake(['https://packs.example.com/*' => Http::response((string) file_get_contents($zipPath), 200)]);
|
||||
|
||||
$tempRoot = storage_path('app/temp');
|
||||
$before = File::isDirectory($tempRoot) ? File::directories($tempRoot) : [];
|
||||
|
||||
try {
|
||||
$pack = $this->service->installFromUrl('https://packs.example.com/pack.zip', null);
|
||||
|
||||
$this->assertSame($identifier, $pack->identifier);
|
||||
|
||||
$after = File::isDirectory($tempRoot) ? File::directories($tempRoot) : [];
|
||||
$this->assertSame(
|
||||
[],
|
||||
array_values(array_diff($after, $before)),
|
||||
'설치가 성공했는데 storage/app/temp 에 다운로드 임시 디렉토리가 남았다'
|
||||
);
|
||||
} finally {
|
||||
@unlink($zipPath);
|
||||
File::deleteDirectory(base_path('lang-packs/'.$identifier));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 코어 ja 번들 픽스처용 manifest 를 만듭니다.
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user