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

@@ -160,6 +160,7 @@ CRUD 를 바꾸고 싶으면 이 4종 중 하나를 잡으면 되고, 이 모듈
- [ ] `_bundled` 에서만 수정하고 `php artisan module:update sirsoft-ecommerce --force` 로 반영
- [ ] manifest version 상향 시 `package.json` · `package-lock.json` · `composer.json` 동기화 + CHANGELOG 기재
- [ ] 스키마 변경 시 마이그레이션(한국어 comment + `down()`) + 기설치본 백필용 업그레이드 스텝
- [ ] 업그레이드 스텝·데이터 마이그레이션이 설정 파일을 새로 쓰면(`File::put`) 바로 뒤에 `FilePermissionHelper::inheritOwnershipFromParent($path)` — `sudo` 코어 업데이트 안에서 root 로 실행되어 그 파일이 root 소유로 남으면 이후 웹 프로세스의 설정 저장이 영구 실패한다. 번들 확장 `upgrades/**` 전수를 파일시스템에서 파생해 검사하는 패리티 테스트가 누락을 잡는다
- [ ] 발행 훅 추가·이름 변경 시 `php artisan ext:docgen` 재실행 (구독하는 확장의 계약이 바뀝니다)
- [ ] API 표면 변경 시 `php artisan api:docgen --scope=module:sirsoft-ecommerce` 재실행 + `docs/api/**` 갱신
- [ ] 레이아웃 JSON 변경 시 빌드 없이 update 만 — 신규 Tailwind 클래스는 빌드된 CSS 에 존재하는지 확인
@@ -6,6 +6,10 @@
## [1.2.1] - 2026-09-06
### Fixed
- `sudo` 로 코어를 업데이트할 때 업그레이드 단계가 저장하는 설정 파일이 root 소유로 남을 수 있던 문제를 수정했습니다. 저장 뒤 폴더 소유자와 같게 맞춥니다.
### Changed
- 입금 기한 만료 주문 자동취소가 카드 등 결제창 결제까지 대상에 포함합니다. 종전에는 무통장입금·가상계좌만 정리되어, 결제창까지 갔으나 결제가 끝나지 않은 주문은 정리하는 주체가 없어 계속 남았습니다. 이제 주문 후 24시간이 지나면 함께 취소되며 미리 차감된 마일리지도 돌아옵니다. 결제가 이미 완료된 주문과 입금 대기 중인 가상계좌 주문은 대상이 아니며, 주문설정의 「만료 주문 자동취소」를 끄면 종전처럼 동작합니다.
@@ -2,6 +2,7 @@
namespace App\Upgrades\Data\Ext\Modules\SirsoftEcommerce\V1_0_0\Migrations;
use App\Extension\Helpers\FilePermissionHelper;
use App\Extension\Upgrade\DataMigration;
use App\Extension\UpgradeContext;
use App\Support\ExtensionStoragePath;
@@ -69,6 +70,8 @@ class AbsorbLegacyDueDaysIntoAutoCancelDays implements DataMigration
unset($settings['vbank_due_days'], $settings['dbank_due_days']);
File::put($path, json_encode($settings, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
// sudo 코어 업데이트 경로에서 root 로 실행되면 새로 만든 파일이 root 소유로 남는다 — 부모 소유권 상속 (#651)
FilePermissionHelper::inheritOwnershipFromParent($path);
$context->logger->info('[ecommerce:1.0.0] 구 입금기한 키 정리 완료');
}
@@ -2,6 +2,7 @@
namespace App\Upgrades\Data\Ext\Modules\SirsoftEcommerce\V1_0_0\Migrations;
use App\Extension\Helpers\FilePermissionHelper;
use App\Extension\Upgrade\DataMigration;
use App\Extension\UpgradeContext;
use App\Support\ExtensionStoragePath;
@@ -100,6 +101,8 @@ class NormalizeCurrencyBaseUnit implements DataMigration
$settings['currencies'] = $currencies;
File::put($path, json_encode($settings, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
// sudo 코어 업데이트 경로에서 root 로 실행되면 새로 만든 파일이 root 소유로 남는다 — 부모 소유권 상속 (#651)
FilePermissionHelper::inheritOwnershipFromParent($path);
$context->logger->info(sprintf(
'[ecommerce:1.0.0] 통화 base_unit 정규화 완료 (기본=%s, base_unit=%d, 환율 스케일=%s)',
@@ -2,6 +2,7 @@
namespace App\Upgrades\Data\Ext\Modules\SirsoftEcommerce\V1_0_0\Migrations;
use App\Extension\Helpers\FilePermissionHelper;
use App\Extension\Upgrade\DataMigration;
use App\Extension\UpgradeContext;
use App\Support\ExtensionStoragePath;
@@ -94,6 +95,8 @@ class NormalizeCurrencyLocales implements DataMigration
$settings['currencies'] = $currencies;
File::put($path, json_encode($settings, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
// sudo 코어 업데이트 경로에서 root 로 실행되면 새로 만든 파일이 root 소유로 남는다 — 부모 소유권 상속 (#651)
FilePermissionHelper::inheritOwnershipFromParent($path);
$context->logger->info(sprintf(
'[ecommerce:1.0.0] 통화 locales 정합화 완료 (지원 언어=%s)',
@@ -2,6 +2,7 @@
namespace App\Upgrades\Data\Ext\Modules\SirsoftEcommerce\V1_0_0\Migrations;
use App\Extension\Helpers\FilePermissionHelper;
use App\Extension\Upgrade\DataMigration;
use App\Extension\UpgradeContext;
use App\Support\ExtensionStoragePath;
@@ -50,6 +51,8 @@ class RemoveLegacyDefaultLanguage implements DataMigration
unset($settings['default_language']);
File::put($path, json_encode($settings, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
// sudo 코어 업데이트 경로에서 root 로 실행되면 새로 만든 파일이 root 소유로 남는다 — 부모 소유권 상속 (#651)
FilePermissionHelper::inheritOwnershipFromParent($path);
$context->logger->info('[ecommerce:1.0.0] 구 default_language 키 정리 완료 (코어 언어 일원화)');
}
@@ -2,6 +2,7 @@
namespace App\Upgrades\Data\Ext\Modules\SirsoftEcommerce\V1_0_2\Migrations;
use App\Extension\Helpers\FilePermissionHelper;
use App\Extension\Upgrade\DataMigration;
use App\Extension\UpgradeContext;
use App\Support\ExtensionStoragePath;
@@ -84,6 +85,8 @@ class PruneEmptyShippingCountryNameLocales implements DataMigration
// 인코딩 플래그는 EcommerceSettingsService 의 저장부와 동일해야 한다.
// 다르면 이 스텝이 국가명과 무관한 값(URL 등)의 이스케이프까지 조용히 바꿔 쓴다.
File::put($path, json_encode($settings, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
// sudo 코어 업데이트 경로에서 root 로 실행되면 새로 만든 파일이 root 소유로 남는다 — 부모 소유권 상속 (#651)
FilePermissionHelper::inheritOwnershipFromParent($path);
$context->logger->info(sprintf(
'[ecommerce:1.0.2] 국가명 빈 로케일 키 %d개 제거 완료 (국가 %d개 검사)',
@@ -2,6 +2,7 @@
namespace App\Upgrades\Data\Ext\Modules\SirsoftEcommerce\V1_0_5\Migrations;
use App\Extension\Helpers\FilePermissionHelper;
use App\Extension\Upgrade\DataMigration;
use App\Extension\UpgradeContext;
use App\Support\ExtensionStoragePath;
@@ -104,6 +105,8 @@ class BackfillMileageEarnRounding implements DataMigration
$settings['currency_rules'] = $rules;
File::put($path, json_encode($settings, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
// sudo 코어 업데이트 경로에서 root 로 실행되면 새로 만든 파일이 root 소유로 남는다 — 부모 소유권 상속 (#651)
FilePermissionHelper::inheritOwnershipFromParent($path);
$context->logger->info(sprintf(
'[ecommerce:1.0.5] 적립 절사 기준 백필 완료 (%d개 통화 규칙 → %s / %s)',