Commit Graph
429 Commits
Author SHA1 Message Date
HeuJung 0253c1aa68 fix(core): sudo 업데이트의 root 캐시 산출물 소유권 정상화 + 캐시 쓰기 fail-soft
클린 7.0.9→7.0.10 실서버 업그레이드에서 전면 500 재발. 치명점을 캐시 파일
내용 역산으로 확정 — sha1('g7:_idx:g7:core') = 모든 remember 가 갱신하는
G7 캐시 키 인덱스 파일이 업데이트 마지막 root 쓰기(cache:clear 직후 버전
bump·상태/훅 캐시 재생성)로 root 소유 생성되면, 웹 프로세스의 모든 캐시
쓰기가 인덱스 갱신에서 Permission denied 로 죽어 부팅 경로가 500 이 된다
(로거 도달 전이라 laravel.log 공백). 직전 커밋의 자식측 게시 게이트만으로
부족했던 이유: 마지막 root 쓰기의 주체가 구코드 부모라 그 이후에 신코드가
개입할 지점이 없다.

- 원인 수정: CoreUpdateService::normalizeRuntimeOwnershipAfterRootRun —
 root 실행 시 storage/framework/cache·bootstrap/cache·storage/app/ext-bundles
 를 디렉토리 소유자 기준 재귀 정상화 + 그룹 쓰기 동기(업그레이드 로그
 정상화 선례 확장). 부모·자식 커맨드의 모든 흐름 종료부에 짝으로 배선 —
 이후 업데이트는 root 산출물을 남기지 않고 과거 잔재도 재귀 자가 수복
- 안전망: AbstractCacheDriver 쓰기 fail-soft — put/forget/putMany 는 false,
 remember 는 콜백 1회 실행 보장 후 저장 실패를 삼키고 결과 반환(무캐시
 동작), 경고 로그는 조합당 프로세스 1회. 구코드가 남긴 오염처럼 신코드가
 선제 개입 못 하는 상황에서도 화면이 죽지 않는다 — 캐시는 최적화다
- red→green: CacheDriverWriteFailSoftTest 4케이스, CoreUpdateRuntimeOwnershipTest
 (비-root no-op + 종료부 짝 호출 소스 훑기)
2026-08-25 19:00:12 +09:00
HeuJung 0bb33e3baa fix(core): root 프로세스의 terminating 정적 게시를 웹 자가 치유로 위임
sudo 코어 업데이트(7.0.9→7.0.10 실서버)에서 자식 프로세스(신코드, root)의
terminating 게시가 소유권 복원 이후 시점에 실행되며 캐시 락 샤드 디렉토리
(storage/framework/cache/data/xx)와 병합 번들(storage/app/ext-bundles)을
root 소유로 남겼고, 이후 웹 프로세스의 캐시 쓰기가 그 샤드에 해시되는 순간
Permission denied 로 죽어 전면 500 이 됐다 (laravel.log 무기록 — 로거 도달 전).

normalizeOwnership 은 게시 트리(build/ext)만 다뤘다 — 게시의 간접 write-set
(캐시 락·번들 빌드)이 사각이었다. 뒤쫓아 chown 하는 대신 root 프로세스에서는
terminating 자동 게시를 예약하지 않고 다음 웹 렌더의 자가 치유(웹 계정)에
위임한다. 명시적 ext-static:publish 는 게이트 밖(운영자 책임 — 규정 §6).

- 시나리오 매니페스트에 process_user(web/root_cli) 축 신설 — uid 조합 실측
 부재가 이 결함을 통과시킨 구조적 원인 (기존 마커 전수에 web 부여)
- red 소급 증빙: 게이트 부재 커밋본에서 신규 케이스 실패 확인 → 15/15 green
2026-08-25 17:37:24 +09:00
HeuJung 5ba7a83597 feat(core,engine): 부트스트랩 리소스 정적 게시(bake) 및 폴백 체계 도입
공개 제보 https://github.com/gnuboard/g7/issues/122 대응 — 초기 부트스트랩
리소스(다국어 병합·컴포넌트 정의·라우트·확장 번들·템플릿 dist)를 캐시 버전
디렉토리(public/build/ext/{v}/)에 실파일로 게시해 웹서버가 rewrite 전에 직접
서빙한다. 부트 임계 경로의 PHP 왕복을 제거하고(실측 TTFB 131~144ms → 1~7ms),
미게시·부분게시·GC 직후에는 fetch·태그·번들 3계층이 종전 API 로 즉시 폴백한다.

- 게시: 원자적 tmp→rename→manifest(존재=완료), 캐시 락 단일 실행, 인라인 GC
 (현재+직전 1개), incrementExtensionCacheVersion 단일 지점 terminating 트리거
 + blade 자가 치유 + 설치기 태스크(best_effort) + 일일 cleanup 스케줄,
 sudo 업데이트 대비 소유권 정상화(normalizeOwnership)·prune/백업 제외
- 프론트(engine-v1.61.0): blade 주입 cache_version 1급 시드(이중 부트 로드 제거),
 fetchStaticFirst 즉시 폴백, ComponentRegistry 버전 키드 매니페스트,
 ModuleAssetLoader 번들 정적→레거시 폴백, asset-url-recovery staticToLegacy 역변환
- 폴백 API 품질: lang/components/routes ETag+304 + 환경 분기 Cache-Control,
 열화 라우트 스냅샷 공개 캐시 금지(서버측 캐시 회피와 대칭), 게시 .htaccess
 mod_deflate + nginx gzip 스니펫(압축 전송량 회귀 방지)
- SEO 정합: 봇 HTML 은 GC 대상 정적 URL 미사용(allowStatic:false), props $switch
 봇측 해석 구현(engine-v1.56.0 패리티), 패리티 룰 expression-dialect 그룹 신설,
 상주 allow 헤더 제거로 잠금 복원, _comment* 접두 주석 키 분류
- 검증: 전 수정 red→green 4단계, Playwright 라이브 21건, Chrome MCP 24축+M1~M3,
 봇 curl 3축, 캐시 저장소(file/redis/database) 축 판정, 히스토리·공개이슈·커밋
 이력 전수 재조사 반영
- 코어 7.0.10, engine-v1.61.0. kill-switch: G7_STATIC_CACHE=false
2026-08-25 17:02:53 +09:00
HeuJung 56836a2b66 Merge branch 'develop' 7.0.9 2026-08-24 17:55:37 +09:00
HeuJung 78bb192bb0 fix(docs): 신규 번들 확장이 README 인벤토리에서 누락되던 문제 수정 및 재발 방지
7.0.9 에 추가한 비즈뿌리오 플러그인과 그 일본어 언어팩이 README.md·README.ko.md
인벤토리 표 양쪽에서 빠진 채 릴리즈 직전까지 남아 있었다.

manifest·CHANGELOG·버전 동기는 기존 하네스가 잡지만 README 인벤토리 표를 보는
검사는 없었다. 누락되어도 오류가 나지 않고 릴리즈 절차도 그대로 통과하므로,
공개 저장소 첫 화면에서 그 확장만 없는 상태로 배포된다.

- 두 README 의 플러그인·언어팩 표에 누락 행 추가
- check-readme-bundled-inventory.cjs 신설 — 네 종류(_bundled 모듈/플러그인/
 템플릿/언어팩)를 두 README 와 대조. 학습용 샘플은 현행대로 제외
- Stop 훅에 등록해 세션 종료 전 자동 검출
- 검출력 확인: 수정 전 README 로 4건(플러그인 2 + 언어팩 2)을 red 로 잡는다
2026-08-24 17:49:33 +09:00
HeuJung 9ff363bd14 Merge branch 'develop' 2026-08-24 17:27:59 +09:00
정정홍andGitHub 7b26c4beec Merge pull request from gnuboard:HeuJung/issue597
HeuJung/issue597
2026-08-24 17:07:41 +09:00
HeuJung 28d6a7752c fix(core,message_bizppurio): 브랜치 검증 발견 결함 4건 — 스냅샷 회귀·조건부 skip·낡은 주석
출시 전 /validate-branch 통합 검증에서 발견한 결함을 처리한다.

- BindingShape 라우팅 diff 스냅샷이 중간 상태에서 구워져 HEAD 가 red 였다.
 발산 517건을 덤프해 신규 41건이 전부 객체·배열 리터럴 바인딩(구 정규식
 오판 계열)이고 유해 지점 스냅샷은 이미 green 임을 확인한 뒤 기록값을 맞춘다.
- 채널 잔재 정리 검증이 게시판 모듈 활성 환경에서만 실행돼 대부분의 실행에서
 미검증으로 남았다. 정리 로직이 소유자를 묻지 않는 실제 계약대로 모듈 소유
 정의를 테스트 안에서 구성해 무조건 실행되게 한다.
- activity_log 주석이 폐기된 설계(조회 전용 전환·콘솔 위임)를 서술하고 있어
 현행 사실로 정정한다. 사용자 문구는 바뀌지 않는다.
- 설정성 테이블의 상한 없는 조회 근거와 seeder 반환 키 타입을 코드에 남긴다.
2026-08-24 17:03:42 +09:00
HeuJung 0bccd867a7 chore(release): 7.0.9 출시 준비 — 출시일자 정렬·공개 배포물 정합 결함 정리
7.0.9 릴리즈 사전 점검에서 공개 배포물에 실릴 결함을 전수 정리한다.

출시일자: 이번 사이클에 버전이 오르거나 새로 추가된 대상 10건의 CHANGELOG
출시일을 실제 공개일로 정렬. 결제 3종은 직전 릴리즈 페이로드로 이미 나갔으므로
제외했다.

내부 역할 호칭: 공개 배포물 26파일 49곳을 중립 표현으로 치환. 이미 공개된
페이로드에는 실질 0건이라 이번 릴리즈가 첫 유입이었다.

최초 출시 규격: 신규 플러그인과 그 언어팩의 CHANGELOG 를 선례 규격으로
재구성. 작성 중 확인되지 않은 서술 2건은 코드 실측으로 교정했다.

번들 ja 언어팩: 번역 값에 남은 한글 40건 정정. 같은 용어가 세 갈래로 갈려
있던 표기도 함께 통일했다. 정정값의 근거는 저장소가 이미 갖고 있었다 —
테스트가 정답으로 단언하는 값과 배포물이 어긋난 상태였다.

재발 방지: 원인은 번역 생성기의 용어집 미등록이므로 출력만 고치면 다음
빌드에서 되살아난다. 용어집에 8건을 등록하고, 규정 3건과 잔존 검출 룰을
신설했다. 룰은 수정 전 배포물로 red 가 되는지를 픽스처로 고정해 판정기가
모집단에 닿는지를 증명한다.
2026-08-24 16:18:52 +09:00
HeuJung e7fa1b5535 feat(message_bizppurio): 알림 템플릿 편집 통합·검수 의견·관리탭 개선 및 언어팩 번역 보존 결함군 수정
비즈뿌리오 알림톡 UX 개편 후속:
- 코어/게시판/이커머스 알림 템플릿 [편집] 모달에 확장 채널 편집 영역
 (extension_point 2종 + hidden_template_editor 채널 메타)을 신설하고,
 알림톡 템플릿·문자(SMS)·수신자 규칙을 한 창에서 통합 저장하도록 개정
 (행 하단은 상태 요약 전용, 승인 여부 2단 배지)
- 검수 신청에 검수자 전달 의견(comment) 동봉 — kapi request 로만 전달,
 행에는 저장하지 않음 (FormRequest 신설 + API 문서 백필)
- 관리 탭 모바일 카드뷰·도구줄 코어 관례 통일, 사이트맵 알림 정의
 다국어 라벨 결측 수정 + 코어 정의 라벨 패리티 테스트 신설

언어팩 번역 소실·보존 결함군 (보완 실측 → 커밋 전 점검에서 연쇄 확정,
전부 실패 테스트 선행 후 수정):
- [기본값 복원]이 활성 언어팩 번역(ja)을 영구 소실 → 복원 기본값에
 시딩과 같은 주입기(SSoT)로 팩 로케일 병합 (notification·identity)
- 코어 알림/본인인증 시더의 언어팩 주입 전면 불능 → 주입기가 연관/리스트
 양형태 수용 + identity 시더의 config 복합 키 보존
- 실패한 언어팩 업데이트가 active 팩을 installed 로 방치 → 상태 복원 확장
- 병합·제거의 사용자 수정 보존 판정 사문(연관 전제 isset) → dot-path 판정
 교정, 팩 주입 저장의 user_overrides 오염 차단(시딩 바인딩), 템플릿
 2모델 translatableTrackableFields 선언(beta.4 설계 누락), 같은 프로세스
 활성화 시 시더 번역 필터 stale(캡처 인스턴스 캐시) 교정
- 7.0.9 업그레이드 스텝 신설 — 활성 팩 seed 재동기화로 기설치본의 소실
 번역 자동 복구 (멱등·운영자 수정 보존·팩별 실패 격리)
2026-08-24 14:51:37 +09:00
HeuJung 40f62e79aa docs(changelog): 게시판·이커머스 CHANGELOG 의 비즈뿌리오 기능 항목 제거
템플릿 작성·검수·발송 기능의 실체는 전부 플러그인(sirsoft-message_bizppurio)
디렉토리에 있고 두 모듈 화면에는 주입만 되므로, 그 기능 서술은 플러그인
CHANGELOG 가 정합 위치다. 모듈 자신의 변경(통합 탭 선언 지원)을 기록한
Changed 항목만 남긴다.
2026-08-22 23:05:31 +09:00
HeuJung e17731d8cc feat(message_bizppurio): 알림톡 템플릿 라이프사이클 개편 — DB 기반 작성·검수·승인
비즈뿌리오 알림톡 템플릿을 콘솔 위임(발송 전 실시간 조회) 방식에서 시스템 내
작성(draft) → 검수 신청(requested) → 승인(approved) 라이프사이클로 개편한다.
발송 판정의 SSoT 를 DB(bizppurio_templates)로 옮기고 발송 전 실시간 조회를 폐지.

- 알림↔템플릿 바인딩 모델(notification_bindings) 제거, 알림 1건당 템플릿 1행으로 대체
- 검수 신청: template_code 자체 채번(codeCheck 재시도) → kapi add/update → request
- 상태 동기화: 30분 스케줄러 + 수동 새로고침, 승인 전이 시 content 를 approved_content 로 동결
- SMS 본문 언어별 입력 복원(수신자 로케일 발송), SMS 단독 선택 시 알림톡 미발송
- 3면(코어/게시판/이커머스) '비즈뿌리오' 통합 탭 + 플러그인 '알림 템플릿 관리' 화면
- 중복 검수 신청은 서버 원자 선점(claimForInspection 조건부 UPDATE)으로 차단
- admin_basic 1.0.6 / board 1.0.5 / ecommerce 1.1.2: 채널 서브탭 통합 탭 선언(tab_channels) 지원
- 검증: 계획서 대비 5라운드 전수검증, §6.3 실측 매트릭스 Playwright 19 고정,
 PHPUnit 421 / Vitest 228 green, audit 0 error
2026-08-22 22:44:57 +09:00
HeuJung 6a8a537f10 feat(message_bizppurio): 임시 삭제된 비즈뿌리오 플러그인 복구 및 현행 규정 정합화
32afe9530 에서 게시판 반응 기능과 함께 임시 제거됐던 비즈뿌리오 메시징
플러그인 본체(137 파일)와 일본어 번들 언어팩(9 파일)을 삭제 직전 상태
(32afe9530~1)로 복구한다. 템플릿 신청·승인 개편의 기반 작업.

복구 범위
- plugins/_bundled/sirsoft-message_bizppurio 전체 + 번들 ja 언어팩
- 공유 파일의 비즈뿌리오 참조 복원: build-language-pack-ja.cjs 팩 정의,
 api-doc-unfilled-baseline.json(32건), docs/backend/api/README.md 표 행,
 audit coverage 노트·vite-sourcemap-env-gate 룰 주석, via 테스트 주석,
 ·AGENTS.md 확장 API 표(자동 재생성), 라우팅 패리티 스냅샷(+1)

삭제 이후 강화된 규정 2건 정합화
- TokenCheckController: 예외 원문을 메시지 키 자리에 전달하던 422 응답을
 키(token_check.failed) + errors.bizppurio_message 페이로드로 분리
 (GenericCatchStatusCodeContractTest 계약). 관리자 토스트는 errors 페이로드로
 상세 사유를 계속 표시하도록 레이아웃 동기 수정, lang ko/en/ja 키 추가
- AlimtalkTemplateController::index: base Request 주입 금지 룰에 따라
 AlimtalkTemplateListRequest FormRequest 신설 (형태 검증만 — kapi 위임 유지)

미복원(의도)
- 게시판·이커머스 CHANGELOG 의 알림톡 연결 문구 2줄은 연결 방식이 로
 재설계되므로 되살리지 않고, 완료 시점에 새 동작 기준으로 차기 버전에 기재

검증: TokenCheck 7 + AlimtalkController 10 + GenericCatch 계약 3 (PHPUnit),
플러그인 레이아웃 Vitest 137건, BindingShape 라우팅 패리티 8건 green.
audit 는 복구 전부터 baseline 처리된 API 문서 미채움 32건만 잔존.
2026-08-22 22:39:36 +09:00
정정홍andGitHub acdff53792 Merge pull request from gnuboard:HeuJung/issue610
feat(content): 본문 이미지 목록 썸네일·og:image 폴백 전 티어 구현
2026-08-22 22:26:42 +09:00
HeuJung 1ba67ca7cf feat(content): 본문 이미지 목록 썸네일·og:image 폴백 전 티어 구현
공개 이슈 https://github.com/gnuboard/g7/issues/22 — 본문에 삽입한 이미지가
카드/갤러리 목록 썸네일과 공유 미리보기(og:image)에 반영되지 않던 공백을
코어+3모듈+2템플릿에서 해소.

- 코어 7.0.9: HtmlImageExtractor(내부 이미지 한정, origin 정규화 SSoT 재사용)
 + seo.og_image_default 사이트 기본 공유 이미지 설정 + SeoMetaResolver 폴백 체인
- board 1.1.0 / ecommerce 1.2.0 / page 1.1.0: content_thumbnail_url 캐시 컬럼,
 saving 추출(html 모드 한정·첨부 우선·비밀글 게이트 유지),
 filter_content_thumbnail 훅, 기존 데이터 백필 업그레이드 스텝
- ecommerce 카테고리 og:image 생산자 신설, page og:description 死키 정정
- sirsoft-basic 1.1.2 og 바인딩 정정, admin_basic 1.0.7 SEO 탭 업로더(+ja 팩 2종)
- 검수 중 발견한 text 모드 오캐시 결함은 실패 테스트 선행 후 수정
2026-08-22 22:21:54 +09:00
HeuJung 14eb2e39e4 Merge branch 'develop' 7.0.8 2026-08-22 11:07:52 +09:00
HeuJung ca4834bbb9 fix(release): 7.0.8 사전점검 전수조사 — 릴리즈 차단 2건 포함 결함 7건 수정 및 출시일 정렬
- pay_nhnkcp 1.0.3 분리: 관리자 API 권한 게이트 변경분이 이미 배포된 1.0.2
 섹션에 소급 누적돼 있어 배포본과 어긋나고 업데이트 감지도 불가하던 것을
 manifest/package/composer/lock 동기와 함께 정정
- 공개 시나리오 매니페스트의 내부 경로 참조 제거 — 릴리즈 파일 누출 검사가
 error 로 발행을 차단하던 상태 해소 (내부 정적 검사 연계는 도구 비귀속 서술로 이관)
- 모듈/플러그인/템플릿 수동 설치에서 깨진 zip·manifest 누락 같은 사용자 입력
 오류가 500 으로 위장되던 422 계약 회귀 복원 — 서비스 경계에서 도메인 예외로
 승격해 상태코드와 실패 사유를 함께 보존 (회귀 테스트 동반)
- 본인인증 정책 검색 버튼이 입력 중인 검색어를 반영하지 않고, 초기화 후에도
 입력창에 이전 검색어가 남던 문제 수정 — 폼 자동바인딩 옵트아웃 + 명시 상태
 전환, E2E 회귀 스펙과 트러블슈팅 사례 동반
- 프록시 URL 검증 비문자열 분기의 :schemes 치환 누락 보정 (회귀 테스트 동반)
- 7.0.8 사이클 출시일자를 2026-08-22 로 정렬 (코어·엔진·확장 7종·언어팩 3종,
 버전·콘텐츠 무변경) 및 설치본 언어팩 동기
2026-08-22 10:16:08 +09:00
정정홍andGitHub df918de2a6 Merge pull request from gnuboard:HeuJung/issue605
fix(security): KVE-2026 신고 4건 조치 — 관리자 API 권한 게이트 + 금전 처리 경쟁 조건
2026-08-22 09:13:33 +09:00
HeuJung 494e581973 fix(security): KVE-2026 신고 4건 조치 — 관리자 API 권한 게이트 + 금전 처리 경쟁 조건
KISA 신고 4건(KVE-2026-1886/1887/1893/1894)을 검증하고, 미수정 2건과
동종 결함 전수 조사에서 나온 결함을 함께 조치했다.

권한 게이트 (KVE-2026-1893)

- NHN KCP 관리자 주문 연동 7경로가 admin 보유 여부만 보고 세부 권한을 보지 않아,
 업무 권한 없는 관리자가 주문번호·결제정보·수령인 연락처를 조회하고 에스크로
 배송등록까지 할 수 있었다. 조회는 orders.read, 등록은 orders.update, 설정성
 경로는 settings.read 로 게이트해 다른 PG 연동과 강도를 맞췄다.
- 마케팅 채널 저장은 코어 플러그인 설정과 같은 저장소를 덮어쓰는 우회 경로라
 core.plugins.update 를 부착했다.

첨부 해시 노출 (KVE-2026-1894 잔재)

- 비밀글의 썸네일 URL 이 목록·상세 응답에 그대로 실려 첨부 해시가 노출됐다.
 이미지 서빙은 이미 차단돼 있었으나 식별값 자체가 나갔다. 첨부 목록과 같은
 게이트를 써서 값만 가리고 필드는 유지한다.

경쟁 조건 (KVE-2026-1886 + 전수 조사)

- 쿠폰 차감을 조회 후 갱신에서 조건부 UPDATE 로 바꿔 1회 제한 쿠폰의 동시
 사용을 막고, 선점당한 주문은 409 로 되돌린다.
- 라이브 병렬 재현에서 그 롤백이 동작하지 않는 것을 확인했다. Action 훅 기본값이
 큐 래핑 + afterCommit 이라 금전 처리가 호출자 커밋 뒤에 실행되고 있었다.
 쿠폰·적립금 차감/복원 5개 구독에 sync 를 선언했고, 회귀 테스트는 손 등록이
 아니라 실제 등록 경로를 태워 고정했다.
- 동시 부분취소의 취소 누적 컬럼 lost update, 적립 lot 의 read-modify-write,
 주문옵션당 적립 lot 중복 생성을 각각 행 잠금·컬럼 연산·유니크 제약으로 막았다.
 기설치본의 중복 lot 은 인덱스 생성 전에 금액을 합산해 한 줄로 통합한다.

규정·문서

- sync 판정 기준을 hooks.md 에 명문화하고 /AGENTS.md Listener 표와
 coverage manifest 에 반영했다. 같은 증상을 다시 만났을 때의 진단 경로를
 트러블슈팅 사례로 남겼다.
2026-08-22 01:19:36 +09:00
정정홍andGitHub 510e498fec Merge pull request from gnuboard:HeuJung/issue604
fix(engine): 구형 Safari 부팅 실패 해소 및 배포 번들 브라우저 하한 회귀 방지
2026-08-21 21:07:33 +09:00
HeuJung 0db8f9c5fb fix(engine): 구형 Safari 부팅 실패 해소 및 배포 번들 브라우저 하한 회귀 방지
코어 엔진 번들의 정규식 lookbehind 2건이 Safari 16.4 미만에서 파싱 자체를
거부당해 iOS 15 대 전 기기에서 SPA 가 통째로 뜨지 않았다. 정규식 리터럴은
스크립트 파싱 단계에서 검증되므로 그 문법을 모르는 엔진은 파일을 한 줄도
실행하지 못하고, 번들이 async/defer 없는 동기 classic 스크립트라 폴백 경로도
없었다. 빌드 타깃(es2020)이 이를 막지 못한 이유는 ES 연도와 브라우저 지원
연도가 다르기 때문이며, 정규식 리터럴 문법은 다운레벨 자체가 불가능해
어떤 타깃 설정으로도 걸러지지 않는다.

- 두 정규식을 lookbehind 없는 형태로 교체(engine-v1.60.6). 선행 따옴표·구분자를
 소비한 뒤 캡처 그룹으로 분기하며, 식별자 인덱스가 match[1] → match[2] 로
 이동한다. 무작위 200,034 표본 퍼징에서 교체 전후 결과 불일치 0건.
 파싱 하한 실측 Safari 16.4 → 14.1 (제보자 기기 15.6 포함).

- 부팅 실패 안내를 사유별로 가른다. 번들을 받았는데 실행되지 않은 경우와
 끝내 받지 못한 경우는 사용자가 취할 행동이 정반대인데 같은 문구였다.
 사유는 추측이 아니라 window error 이벤트로 SyntaxError 를 관측해 판정한다
 (파싱 실패 시 script 는 error 가 아니라 load 를 발생시켜 element 이벤트로는
 구분 불가). 비호환 분기는 새로고침해도 낫지 않으므로 버튼을 렌더하지 않는다.
 인라인 부트스트랩은 ES5 를 유지해야 이 안내 자체가 구형에서 살아남는다.

- 재발 방지: 배포 JS 산출물의 브라우저 하한 초과 문법·API 를 정적 검사로 차단.
 부팅 임계 번들(코어 엔진·템플릿 컴포넌트)은 파싱에 실패하면 안내 화면조차
 렌더되지 않으므로 하한과 같은 버전을 요구하는 정규식 리터럴 문법도 금지한다.
 lookbehind 의 Safari 16.4 는 하한과 정확히 같아 하한 초과만 보는 검사로는
 영원히 잡히지 않았다 — 그 지점이 이번 사각이었다.

- 지원 브라우저 최소 버전(Chrome 111 / Safari 16.4 / Firefox 128)과, 하한 미만
 브라우저에서도 화면 표시와 기본 이용은 유지한다는 방침을 문서에 명시.

부수 수정: network-resilience E2E 4건이 자산 URL extensionless 모드에서 URL
glob 이 한 건도 매칭되지 않아 실패하고 있었다. 같은 파일의 컴포넌트 번들
테스트만 이중 모드를 알고 형제 케이스는 몰랐던 불균형이라 매처를 통일했다.
2026-08-21 20:55:57 +09:00
정정홍andGitHub 80d16c80bc Merge pull request from gnuboard:HeuJung/issue603
fix(extension): 확장 수명주기 캐시 무효화 순서 회귀 및 실패 사유 전달
2026-08-21 17:48:10 +09:00
HeuJung 03cbb99196 fix(extension): 확장 수명주기 캐시 무효화 순서 회귀 및 실패 사유 전달
route:cache 는 새 앱을 부팅해 라우트를 수집하고, 그 부팅의 확장 라우트 프로바이더는
DB 가 아니라 캐시된 활성 확장 목록을 읽는다. 그래서 rebuild 가
invalidate*StatusCache 보다 앞서면 방금 바뀐 상태가 빠진 채 라우트가 박제되고,
라우트 캐시에는 스캔 폴백이 없어 오류도 로그도 없이 404 가 된다. 무효화를 굽기 직전이
아니라 DB 상태 쓰기 직후로 올려, 같은 목록을 읽는 훅 매핑 캐시까지 함께 바로잡았다.
update 경로는 Updating 전이 직후에 비우면 그 창의 오토로드 갱신이 확장을 비활성으로
판정하므로, 상태 복원 직후에 비운 뒤 훅 캐시를 다시 굽는다.

플러그인 라우트 프로바이더에는 활성 게이트가 없어 비활성 플러그인의 API 가 계속
응답했다. 화면·메뉴만 사라지고 기능은 살아 있는 상태였다. 모듈과 같은 기준을 적용했다.

실패 사유가 하위 계층에서 버려져 관리자 화면에 :error 자리표시자가 그대로 노출되던
문제도 고쳤다. 반환 경로를 깨지 않도록 배열 키 reason 과 뒤에 붙인 선택적 out
파라미터로 사유를 실어 올리고, 확장이 수명주기 훅에서 사유를 남길 수 있는 통로를
추가했다. 설치 경로의 광역 RuntimeException catch 는 도메인 예외로 좁혀 원본 키와
파라미터를 응답에 싣는다 — 상태코드 422 는 유지해 사용자 계약을 함께 바꾸지 않는다.
언어팩 화면은 프로덕션에서 예외 원문을 싣지 않는 것이 확정된 계약이므로, 자리를
일반 문구로 채우는 대신 치환 자리 자체를 제거했다. 원문은 종전대로 errors 통로를
거쳐 디버그 모드에서 도달한다.
2026-08-21 17:09:30 +09:00
HeuJung 565f6c0117 chore(pay_kginicis): 7.0.7 배포 이후 변경분을 1.1.2 로 분리
CBT 연결 점검의 프록시 경유 수정과 코어 최소 버전 상향이 이미 배포된
1.1.1 섹션에 누적돼 있었다. 배포본과 내용이 어긋나지 않도록 1.1.2 로 분리한다.
2026-08-21 13:53:49 +09:00
HeuJung d8ca281464 chore(release): 코어 7.1.0 → 7.0.8 하향 및 7.0.7 이후 변경분 출시일 정렬
프록시 설정 추가분을 마이너(7.1.0)가 아닌 패치(7.0.8)로 내보낸다.
7.0.7 이후 변경된 코어·템플릿·플러그인·언어팩의 출시일을 2026-08-21 로 맞춘다.

>=7.1.0 을 요구하던 본인인증 플러그인의 코어 최소 버전을 >=7.0.8 로 내린다 —
그대로 두면 존재하지 않는 버전을 요구해 플러그인이 자동 비활성화된다.
앞선 작업에서 누락된 package-lock.json 버전(1.0.3)도 함께 맞춘다.
2026-08-21 13:53:42 +09:00
정정홍andGitHub 6d2677e7bd Merge pull request from gnuboard:HeuJung/issue600
feat(settings): 코어 아웃바운드 HTTP 프록시 설정 추가
2026-08-20 17:05:39 +09:00
HeuJung a7b7c64573 feat(settings): 코어 아웃바운드 HTTP 프록시 설정 추가
접속 IP 를 제한하는 결제사 API 를 로컬·스테이징에서 연동하려면 서버가
내보내는 요청의 출발지 IP 를 바꿔야 한다. 브라우저 프록시로는 바뀌지 않는
축이라 코어 환경설정으로 도입한다.

게이트는 디버그 모드이며 판정은 OutboundProxy 한 곳이 소유한다. 화면의
조건부 렌더링은 편의일 뿐이라 저장 API 직접 호출을 막지 못하므로, 실질
게이트를 판정 지점에 둔다. 주입·적용 지점은 결과만 소비한다.

적용은 Http::globalOptions 전역 옵션이라 확장의 Http:: 호출까지 함께
경유한다. 외부 연동 규약상 curl 핸들을 직접 다뤄야 하는 확장은
OutboundProxy::curlOptions 로 같은 프록시를 탄다 — KG이니시스 본인인증
승인 요청과 CBT 연결 점검을 이 통로로 편입했다. CBT 의 TCP 443 확인은
원시 소켓으로는 프록시를 태울 수 없어 curl CONNECT_ONLY 로 교체했다.

저장 전 연결 테스트는 저장값이 아니라 제출값을 검사하고, 그 프록시를
거쳤을 때 외부에 보이는 IP 를 함께 보고한다. 운영자가 결제사에 등록할
값이라 저장하고 나서 되짚지 않도록 했다. 적용과 같은 조립을 거치므로
확인한 구성과 저장 후 적용되는 구성이 어긋나지 않는다.
2026-08-20 17:01:27 +09:00
HeuJung 0e8b625436 Merge branch 'develop' 7.0.7 2026-08-19 09:20:00 +09:00
HeuJung 8fa97bc8bd docs(changelog): 7.0.7 릴리즈 공개 제보자 attribution 전수 검사 반영
- 이커머스 「삭제된 PG」 항목에 @Tuwasduliebst 제보 attribution 부착
 (제보 8/12 → 수정 8/14 — 같은 배치 제보 중 유일한 누락)
- 언어팩(ja) 5종의 공개 이슈 파생 번역 항목 11건에 원본 ko attribution 승계
 ( — core-ja/admin_basic-ja 기존 선례와 기준 통일)
- README 기여자 목록 변경 없음(신규 기여자 없음), ko↔ja 동기 검사 통과
2026-08-19 09:17:01 +09:00
정정홍andGitHub f0562a8553 Merge pull request from gnuboard:HeuJung/issue596
docs(changelog): 장바구니 선택 개수 수정에 공개 PR 기여 attribution 반영
2026-08-19 08:55:40 +09:00
HeuJung 5d58fb5c5b docs(changelog): 장바구니 선택 개수 수정에 공개 PR 기여 attribution 반영
공개 PR https://github.com/gnuboard/g7/pull/93 은 내부에서 이미 상위 호환으로
수정 완료된 결함과 중복이라 코드는 이식하지 않고, 지시에 따라 sirsoft-basic
1.1.1 CHANGELOG 의 해당 항목 attribution 에 수정 기여를 병기한다. 동일인의
제보+수정이므로 이슈 번호만 묶고 핸들은 1회 표기.
2026-08-18 23:12:00 +09:00
HeuJung 8bf40465df docs(release): 7.0.7 릴리즈 CHANGELOG 섹션 내 Changed 카테고리 중복 병합
병렬 검수 병합 과정에서 미릴리스 신규 버전 섹션 4곳(pay_kginicis 1.1.1,
pay_nhnkcp 1.0.2, pay_nicepayments 1.0.2, g7-core-ja 1.0.6)에 ### Changed
헤딩이 두 번 생긴 것을 하나로 병합. 불릿 내용은 무변경이며, 이미 공개
배포된 과거 버전 섹션의 동형 중복 12건은 소급 수정 금지 규정에 따라 유지.
2026-08-18 12:55:24 +09:00
HeuJung 6a756bdec1 docs(release): 7.0.7 출시 연기 — 릴리즈 CHANGELOG 27종 날짜 2026-08-18 → 2026-08-19 변경
코어·엔진·모듈 3종·플러그인 10종·템플릿 2종·언어팩 11종의 미공개 working
섹션 헤딩 날짜만 변경 (버전·콘텐츠 무변경).
2026-08-18 11:46:49 +09:00
HeuJung 07c459f0ff Merge branch 'develop' of https://github.com/gnuboard/dev-g7 into develop 2026-08-18 11:04:01 +09:00
HeuJung 932866da8f fix(ecommerce): 숨김 리뷰 이미지의 관리자 썸네일을 한시 서명 URL 로 복구
KVE-2026-1914 S-2 게이트가 숨김(HIDDEN) 리뷰 이미지를 무조건 404 차단해,
관리자 리뷰 화면의 <img> 썸네일(인증 헤더를 실을 수 없는 렌더 경로)이 깨졌다.
게시판·페이지 첨부와 동일 설계로, 게이트를 통과한 관리자 응답의 직렬화
시점에만 30분 한시 서명 download URL 을 발급하고 서빙 엔드포인트가 유효
서명을 허용한다. 무서명·변조·만료 요청 게이트와 전시중 리뷰의 무서명
공개 URL(직접 URL/CDN 포함)은 종전과 동일하다.

숨김 리뷰가 이미지와 함께 직렬화되는 경로는 관리자 응답뿐이므로(공개
목록은 VISIBLE 필터, 작성 직후는 이미지 미로드) 서명 발급이 곧 게이트
통과 자격의 위임이다.
2026-08-18 10:54:26 +09:00
HeuJung 04f1066e66 fix(release): 7.0.7 사전점검 실측 발견 결함 6건 보완 및 규정 반영
브라우저·SEO 실측(T1~T7 매트릭스 + 봇 렌더 스윕)에서 발견된 결함을 보완한다.

- 코어: 회원 일괄 상태변경 응답 메시지의 :count 플레이스홀더 미치환 수정
- 게시판·페이지: 비밀글·삭제글·미발행 첨부 썸네일이 KVE-2026-1914 게이트로
 깨진 것을 한시 서명 preview URL(게이트 통과 직렬화 발급 + 유효 서명 허용)로
 복구 — 무서명·변조·만료 요청 게이트는 종전과 동일
- 페이지: 발행/미발행 전환(after_publish)에도 SEO 캐시·사이트맵 갱신 구독
- 게시판: 게시판 디렉토리(전체 목록 + 내장 최근글)에 열람 권한 필터 적용
- 검색 화면: searchResults 데이터소스 auth_mode=optional 선언으로 로그인
 회원 검색 범위 복구 + data-sources.md 선언 의무 규정화(coverage 등록)
2026-08-18 10:38:50 +09:00
HeuJung 4b986be0b2 Merge: 7.0.7 병렬 검수 수정분 통합 — 구조분해·JSON-LD 중복 구현 단일화, 양측 고유 수정 보존
동일 결함 2건(표현식 배열 구조분해 회귀, JSON-LD 이스케이프)을 양 세션이 독립
구현해 충돌. 해소 기준:

- 평가기 구조분해: JS iterator 시맨틱 구현 채택(구 평가기 new Function 패리티가
 회귀 수정의 본래 의도). 관대(undefined) 바인딩 구현과 그 단언 1건은 폐기.
 단위 테스트는 양측 병합(구조분해 10케이스), E2E·시나리오 축은
 destructuring_param 단일 케이스로 통합. 무관 심볼의 @since 소급 변경은 원복.
- JSON-LD: JSON_HEX_TAG|JSON_HEX_AMP(상위집합) 채택, XSS 단위 테스트 중복 제거.
- 양측 고유 수정 각각 보존: composeTitleSuffix 접미사 조립(타 세션) /
 스케줄 확장 명령 웹 검증 폴백·SeoMetaResolverTest 설정 격리(본 세션).
- min.js 는 병합 소스로 core:build --production 재빌드.

검증: SafeExpressionEvaluator 120/120, SeoMetaResolverTest 68/68, 배포 번들
E2E 6/6. 실측 — 게시판 환경설정 권한 섹션 60컨트롤 렌더, 장바구니 담기 201,
봇 title 접미사 공백 복원·매달린 구분자 제거, 검색 XSS 봇/_escaped_fragment_
양 경로 이스케이프 확인.
2026-08-18 10:16:50 +09:00
HeuJung a1e1706ddc fix(release): 7.0.7 회귀 검수 발견 결함 3건 수정 — 표현식 배열 구조 분해·스케줄 확장 명령 웹 검증·JSON-LD 이스케이프
- 표현식 평가기가 화살표/함수 파라미터의 평탄한 배열 구조 분해(([k, v]) =>, 엘리전 홀)를
 지원하지 않아 배포 레이아웃 60여 파일(게시판 권한 computed·검증 오류 표시)이 평가 실패하던
 7.0.7 평가기 교체 회귀 수정 (engine-v1.60.5) + --production 재빌드.
- 스케줄 저장 검증이 HTTP 문맥에서 확장 커맨드를 해석하지 못하던 문제(확장 프로바이더의
 runningInConsole 등록 게이트로 Artisan 레지스트리 부재)를 프로바이더 $commands 선언 폴백으로
 수정 — 판정 기준(클래스 네임스페이스 + 실제 명령명 대조) 동일, fail-closed 유지.
- 봇 렌더 JSON-LD json_encode 에 JSON_HEX_TAG 추가 — 사용자 입력(검색어·게시글 제목)의
 </script> 조기 종료로 인한 저장형 XSS 차단, schema.org 데이터는 무손실.
- SeoMetaResolverTest 의 og_default_site_name 미고정 환경의존 실패를 setUp 고정으로 격리.
- 루트 CHANGELOG 7.0.7 Security/Fixed 각 1건(기출시 결함만), 시나리오 매니페스트 2건 갱신.
2026-08-18 10:00:01 +09:00
HeuJung 0bb2ab9b49 fix(seo,engine): 7.0.7 검증 발견 결함 수정 — 표현식 구조분해 회귀·타이틀 접미사 조립·JSON-LD 이스케이프
- SafeExpressionEvaluator 교체(engine-v1.60.0)가 구 평가기가 허용하던 화살표
 파라미터 배열 구조분해(([k, v]) / ([, vid]))를 누락해 해당 문법을 쓰는 액션
 params 가 미평가 원문으로 전송, 장바구니 담기/바로 구매가 전 상품 불능이던
 회귀를 수정 (engine-v1.60.5, production 재빌드 동반). 저장소 레이아웃 54파일
 104곳 사용 형태 전수를 단위/E2E 테스트로 잠금
- TrimStrings 가 타이틀 접미사의 선행 공백을 제거해 봇 렌더 제목이
 "제목| 사이트명" 으로 접착되고 빈 제목 화면은 "| 사이트명" 이 매달리던 기존
 결함 수정 — 조립 규칙을 composeTitleSuffix 단일 지점(SSoT)으로 정규화
- JSON-LD 직렬화에 JSON_HEX_TAG 미적용으로 검색어의 </script> 가 스크립트
 컨텍스트를 조기 종료해 실행 가능한 script 요소가 재생성되던 반사형 XSS(기존
 결함) 차단 — 태그 문자 이스케이프, 구조화 데이터 의미는 보존
2026-08-18 09:53:50 +09:00
HeuJung b3d0da9355 fix(release): 7.0.7 릴리즈 검증 발견 결함 전수 처리 및 출시일 8/18 정렬
7.0.7 페이로드 전수 검증에서 발견된 error 4건·warn 14건을 릴리즈 전에
처리했다. 미출시 분량의 자체 결함(회원 통합검색 500, 관리자 스코프 403 의
500 위장 등)이므로 페이로드에 합류시키고, 출시 대상 26개 CHANGELOG 의
버전 섹션 날짜를 2026-08-18 로 정렬했다.

- 통합검색 import 복원 + 이커머스 관리자 typed 403 catch 대칭(테스트 동반)
- admin 판정 스니핑 사설 사본 전수 수렴(BoardResource) + 조건 스캔 테스트
- 스케줄 인터프리터 변형 표기(확장자·버전 접미사) 정규화 차단
- ckeditor5 참조 판정 배치화·fail-safe, 결제 플러그인 진단 페이로드 대칭
- 템플릿 다크 대비·상태 Select value-제어 + --production 재빌드
- Upgrade_7_0_7 잔존 중복 색인 정리 스텝, API 문서·i18n(ko/en/ja) 동기
2026-08-18 08:12:55 +09:00
HeuJung ed985dd175 chore(release): 7.0.7 공개 릴리즈 사전점검 정비 — 누출 단서 주석 정리 + 태그 관례 정합
- 공개 릴리즈 누출 검사 error 3건 해소: 소스 주석의 내부 규정 파일명·내부 스크립트
 경로 참조를 공개 문서 참조/도구 비귀속 표현으로 교체
- warn 4건 해소: 테스트·주석의 내부 역할 호칭을 "운영 실측 제보" 로 정리
- 릴리즈 스크립트(코어·확장)의 버전 태그를 공개 저장소 기존 태그 관례(v 접두사 없음)에
 정합 — 접두사 혼재로 태그 시리즈가 갈라지는 것을 차단
2026-08-17 21:36:15 +09:00
정정홍andGitHub 3ee37e8399 Merge pull request from gnuboard:HeuJung/issue594
fix(security): 스케줄 셸 인터프리터 인라인 코드 우회 차단
2026-08-17 21:02:05 +09:00
HeuJung 2fb452aa44 fix(security): 스케줄 셸 인터프리터 인라인 코드 우회 차단
셸 스케줄 검증이 첫 토큰 basename 만 화이트리스트와 대조하고 뒤 인자를
검증하지 않아, 운영자가 bash 를 등록하면 `bash -c id` 로 임의 OS 명령이
실행됐다(KVE-2026-1653). 인터프리터는 범용 크론 용도로 등록을 허용하되,
스크립트 자리(첫 인자)에 형태 규칙을 적용해 인라인 코드·상대경로·트래버설·
artisan 우회·완전거부형(env/awk/make 등)을 저장·실행 양쪽에서 거부한다.
2026-08-17 20:59:42 +09:00
정정홍andGitHub 19424877e8 Merge pull request from gnuboard:HeuJung/issue573
feat(board,ecommerce,pay,verification,templates,core): 문의 답변 사슬·답글 삭제 정책·검증 계약 + 실패 사유 표면화 전수
2026-08-17 17:12:34 +09:00
HeuJung 3ebbda5d86 feat(board,ecommerce,pay,verification,templates,core): 문의 답변 사슬·답글 삭제 정책·검증 계약 + 실패 사유 표면화 전수
공개 (답변 중복 등록)/(문의 삭제 시 답변 잔존) 수정과 동형 결함 전수 해소.

- 문의 답변 단일성: 1차(피벗 is_answered) + 2차(게시판 리스너 duplicate 마커) 이중 방어,
 경합 경로에서도 사유(reply_already_exists 422)가 보존되도록 훅 반환 계약 확장
- 질문·답변·피벗 생명주기 대칭: 삭제/복원/영구삭제 훅 연동 + 고아 데이터 백필 업그레이드 스텝
- 게시판별 답글 삭제 정책(cascade/block) 신설, 정렬 화이트리스트·per_page 게이트
 (전량 조회 소비처 200/999 를 수용하는 상한 999 — 조였다가 관리자 화면 2곳 422 회귀 즉시 정정)
- 결제/본인인증 플러그인 검증 계약: FormRequest 15종 승격 + 컨트롤러 catch 정합.
 거래 조회 tid 상한은 저장 컬럼(varchar 100) 기준 — 해외 CBT TID(40자) 수용
- onError 토스트 고정 문구 전수 해소(67건/50파일/15확장) — 서버 실패 사유를 그대로 표면화,
 change-password 오변수(response→error) 교정
- 코어 플러그인 설정 검증 안내의 항목 표시명이 스키마 라벨(ko/en) 폴백에 덮여 요청 로케일
 (ja) 라벨을 잃던 회귀 정정 — 번역 등록이 있으면 그것을 우선 (7.0.7 미출시 기능 자체 결함)
- 사전 결함 정리(Icon 등가표 27·darkmode 2·validated 통일), API 문서·CHANGELOG·ja 팩 동기
- develop(60652fdc0) 리베이스: getTable 정비와 병합 — 양측 의도 보존 (충돌 18파일)
2026-08-17 17:04:44 +09:00
정정홍andGitHub 60652fdc07 Merge pull request from gnuboard:HeuJung/issue577
fix(security): 보안 제보 14건 + 유사 결함 전수조사 수정
2026-08-17 16:01:21 +09:00
HeuJung cf1d8ab52c fix(security): 보안 제보 14건 + 유사 결함 전수조사 수정
sir.kr 커뮤니티 제보(Xbuilder 님 외)와 전수조사 발굴분을 코어·게시판·
이커머스·페이지·ckeditor5 전반에 반영.

- 통합 검색 하이라이트: 코어 SearchHighlighter 로 원문 이스케이프 후 강조
 (저장형 XSS 차단, board/ecommerce/page 3중복제 통합)
- 공개 최신글·인기글·관리자 대시보드: 읽기권한 없는 게시판·블라인드·비활성
 게시판 글 필터. 비밀글은 기존 공개 정책대로 제목 노출 유지(본문만 보호)
- 게시판 관리 대시보드 권한 게이트, 이커머스 쿠폰 다운로드·리뷰 대상·주문옵션
 확정 스코프 강화, 취소/환불 항목 검증 회원/비회원 대칭
- 만료 토큰 거부(SetLocale), 회원 탈퇴·정보관리 실패 시 내부 오류 원문 마스킹
- 예외→응답 매핑 정비(generic catch 상태코드), ckeditor 업로드 권한 게이트 정리

정책 정합 정정: 착수 계획이 "비밀글 제목 노출=취약점"으로 전제해 공개 최신글·
대시보드에 넣었던 is_secret 필터는, 저장소가 확정한 "제목 공개, 본문만 보호"
정책(2026-01-02/02-04/06-18/06-19)과 배치되어 되돌림. 읽기권한·블라인드 필터는 유지.
Chrome MCP 실측(T1~T10) + 회귀 테스트로 확인.
2026-08-17 15:46:38 +09:00
정정홍andGitHub 2b5972437b Merge pull request from gnuboard:HeuJung/issue589
HeuJung/issue589
2026-08-17 15:18:07 +09:00
HeuJung febffb173e 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종 신설
2026-08-17 15:17:20 +09:00
정정홍andGitHub db49e8b9b8 Merge pull request from gnuboard:HeuJung/issue588
fix(core): 공개 템플릿 config 캐시 무효화 누락과 확장 캐시 삭제 경로 동종 결함 정비
2026-08-17 13:26:13 +09:00