fix(core,admin_basic): 정적 게시 재게시 누락 3건 수정 + 관리자 수동 복구 UI + sudo core:update 소유권 정합

- 템플릿 update 는 레이아웃 변경 여부와 무관하게 캐시 버전을 올리고(실패 복원 뒤에도), 자산 주소 방식 전환 3경로도 bump 한다
- config:cache 가 컨테이너 인스턴스를 덮어 이후 terminating 재게시가 사라지던 결함을 복원 헬퍼로 차단
- custom/ 변경 감지와 게시가 같은 열거자(재귀·크기 포함)를 쓰고, 서명은 호스트별로 저장
- 캐시 버전·서명 키를 만료시키지 않는다(기본 TTL 24h 로 매일 전체 재생성되던 문제)
- 관리자 > 환경설정 > 일반 「초기 화면 정적 파일」 카드: 상태 조회 + 지금 다시 만들기(확인 모달), 대시보드 알림 버튼 연결, CLI 와 같은 statusReport 소비
- sudo core:update 경로의 root 소유 잔존(설정 디렉토리·임시 폴더·로그·업그레이드 마이그레이션 산출물) 상속·정합화, ext-static 명령 root 경고와 sudo -u 힌트
- 안내·문서·트러블슈팅 4건·audit 룰 ext-cache-version-raw-read·ja 언어팩 동기
This commit is contained in:
HeuJung committed 2026-09-06 15:22:52 +09:00
1 parent d263f74cae
commit de18159986
105 files changed
+4055 -208

No files matched your search

@@ -41,6 +41,76 @@ class TemplateUpdateConfigCacheInvalidationTest extends TestCase
);
}
/**
* 업데이트 tail 은 활성/비활성과 무관하게 **무조건** 캐시 버전을 올린다 (#651 F1).
*
* 종전에는 `if ($previousStatus !== ExtensionStatus::Active->value)` 가드 안에서만 올렸다.
* 활성 템플릿은 `refreshTemplateLayouts()` 의 조건부 bump(레이아웃 변경 건수 > 0)에
* 위임됐는데, 그 조건은 게시 입력 중 레이아웃 축만 보므로 lang/routes/dist 만 바뀐
* 릴리스는 정적 게시본이 immutable 로 stale 하게 남았다. 모듈·플러그인 update 는
* 무조건 bump 다 — 템플릿만 다를 이유가 없다.
*
* @scenario cache_state=warm_current,lifecycle_trigger=template_update,template_type=admin
*
* @effects template_update_always_bumps_cache_version
*/
#[Test]
public function update_template_tail_bumps_cache_version_unconditionally(): void
{
$body = $this->methodSource(
base_path('app/Extension/TemplateManager.php'),
'updateTemplate'
);
$this->assertStringNotContainsString(
'if ($previousStatus !== ExtensionStatus::Active->value)',
$body,
'updateTemplate() 의 bump 가 previousStatus 가드 안에 있으면 활성 템플릿의 lang/routes/dist 변경이 게시본에 반영되지 않습니다.'
);
// 성공 tail + 실패 catch 두 자리 — 최소 2회
$this->assertGreaterThanOrEqual(
2,
substr_count($body, '$this->incrementExtensionCacheVersion();'),
'updateTemplate() 는 성공 tail 과 실패 복원 경로 양쪽에서 캐시 버전을 올려야 합니다.'
);
}
/**
* 실패·복원 경로도 캐시 버전을 올린다 (#651 F2).
*
* 백업 복원이 실패했거나 부분 반영된 디스크가 남을 수 있어, 게시본을 새 버전으로 다시
* 굽는 쪽이 옛 게시본을 그대로 두는 쪽보다 안전하다. bump 실패는 원래 예외를 가리지
* 않도록 삼킨다.
*
* @scenario cache_state=warm_current,lifecycle_trigger=template_update,template_type=user
*
* @effects template_update_failure_bumps_after_restore
*/
#[Test]
public function update_template_failure_path_bumps_after_restore(): void
{
$body = $this->methodSource(
base_path('app/Extension/TemplateManager.php'),
'updateTemplate'
);
$catchAt = strrpos($body, 'catch (\Throwable $e)');
$this->assertNotFalse($catchAt, 'updateTemplate() 의 최외곽 catch 를 찾지 못했습니다.');
$catchBody = substr($body, $catchAt);
$restoreAt = strpos($catchBody, "'status' => \$previousStatus");
$bumpAt = strpos($catchBody, '$this->incrementExtensionCacheVersion();');
$throwAt = strpos($catchBody, 'throw new \RuntimeException(');
$this->assertNotFalse($restoreAt, '실패 경로의 상태 복원 코드를 찾지 못했습니다.');
$this->assertNotFalse($bumpAt, '실패 경로에 캐시 버전 bump 가 없습니다 — 부분 반영된 디스크가 옛 게시본과 함께 남습니다.');
$this->assertNotFalse($throwAt, '실패 경로의 재던지기를 찾지 못했습니다.');
$this->assertTrue($restoreAt < $bumpAt && $bumpAt < $throwAt, 'bump 는 상태 복원 뒤, 재던지기 앞에 있어야 합니다.');
}
/**
* 대상 메서드 본문을 주석 제거 후 반환합니다.
*