https://github.com/gnuboard/g7/issues/125 — 상품 상세설명을 HTML 로 저장할 때
HTMLPurifier 가 모듈 vendor 폴더 안에 정의 캐시를 만들려다 실패해 저장이 매번 500 으로
끝나던 문제를 고친다. vendor 를 읽기 전용으로 두는 표준 배포에서 그 쓰기는 예외가 아니라
PHP 경고로 나오고 Laravel 이 이를 ErrorException 으로 승격시킨다. 캐시는 설정 해시당 1회만
기록되므로 캐시가 영영 생기지 않아 재시도해도 같은 결과였다.
캐시 경로를 storage 아래로 옮기고, 그 경로마저 확보하지 못하면 캐시만 끄고 정화는 그대로
수행한다 — 캐시는 성능 장치이고 정화는 보안 장치라, 전자의 실패가 후자를 건너뛰게 만들면
안 된다. 저장은 성공하므로 운영자에게 도달하는 흔적이 로그 하나뿐이라 error 수준으로 남긴다
(출하 기본 로그 수준이 error 라 warning 은 기본 설치 상태에서 파일에 남지 않는다).
그 과정에서 갈라져 있던 두 축을 코어 한 곳으로 모은다.
- 쓰기 디렉토리 확보: 억제 생성·chmod·setgid·소유권 상속·쓰기 판정 절차가 정적 게시와
정의 캐시 두 곳에 서로 다른 하드닝으로 복제돼 있었다(억제 mkdir·setgid·clearstatcache 가
사본마다 한쪽씩 빠져 있었다). FilePermissionHelper 의 ensureWritableDirectory 와
hardenDirectory 로 통합하고, 실패 사유는 out 파라미터로 올려 정책(조용한 성능 저하 대
시끄러운 실패)은 호출부가 정하게 둔다.
- 확장 저장 경로: storage_path('app/modules/…') 손조립이 30곳에 흩어져 있어 테스트 격리
분기를 넣으려면 사본마다 복제해야 했고, 한 곳만 빠뜨려도 그 확장의 테스트가 운영 설정
파일을 덮어쓴다. 디스크 root 를 단일 출처로 읽는 ExtensionStoragePath 로 전환하고 테스트
분기는 config/filesystems.php 한 줄에서 끝낸다.
함께 고친 것
- 테스트가 운영 라우트 캐시로 부팅해 확장 allowlist 가 라우트 축에서 통째로 무력화되던
문제. 삭제가 아니라 경로를 돌린다 — 라우트 캐시는 확장 작업 전까지 재생성되지 않아,
삭제하면 운영 사이트가 그때까지 라우트 파일 스캔 경로로 떨어진다.
- PHPUnit 프로세스가 확장 vendor 의 제3자 composer 패키지를 오토로드하지 않아 그 패키지를
쓰는 코드 경로가 통째로 테스트 불가였던 문제. 확장 자신의 오토로더를 그대로 쓰면 활성
디렉토리가 _bundled 를 이기고 base path 유추까지 깨지므로, 생성된 맵에서 제3자 항목만
골라 별도 로더로 등록한다.
- 게시 폴더가 setgid 를 갖지 않아, 명령줄과 웹이 번갈아 만든 하위 폴더를 다른 쪽이 쓰지
못하던 문제.
- 관리자 템플릿이 HTML 정화 라이브러리를 직접 지정하지 않아 전이 의존으로 딸려온 구버전이
쓰이던 문제.
동반 산출물
- 규정 표(·AGENTS.md) 6행 + storage-driver/service-repository/testing-guide 문서
- audit 룰 2종 + coverage 6항목. 저장소가 이미 전량 전환돼 전수 실행이 공허 통과하므로
판정식은 픽스처 36건이 잠근다
- INSTALL.md 에 설치 후 파일 권한 절 추가 (vendor 쓰기 권한 불요를 명시)
공개 저장소 이슈 gnuboard/g7 (@bigmsg) 제보에서 출발한 작업이다.
브라우저가 화면을 그리려고 제3자 CDN 에 도달해야 하면, 그 도달 실패는 예외도 로그도
남기지 않고 화면 기능만 조용히 사라진다. 폐쇄망·방화벽·광고차단기에서 재현되는데
자체 서버 로그에는 흔적이 없어 운영자가 원인을 특정할 수 없다. 제보된 것은 편집기
하나였지만 같은 구조가 아이콘·글꼴·코드편집기·압축 라이브러리·설치 마법사·개발
대시보드에 똑같이 있었으므로, 번들 확장과 템플릿 전체를 자체 제공으로 옮겼다.
런타임에 외부로 나가는 것은 주소 검색 서비스 하나만 남았다.
자체 제공만으로는 부족하다 — 자기 서버에서 받는 파일도 실패할 수 있고, 종전에는 그
실패가 무음이었다. CSS 경로에 재시도 계층을 세우고(스크립트 경로와 동형), 서버가 HTML
에 직접 심는 externals 까지 실패를 붙잡아 안내 배너와 [다시 시도]로 표면화했다.
편집기·코드편집기는 확보 실패 시 평문 입력으로 내려앉되 저장 계약을 유지한다.
두 번째 축은 운영자가 CSS 를 덧붙일 자리가 없던 문제다(sir.kr 문의). 확장 디렉토리의
custom/ 을 운영자 소유로 정해, 확장 교체가 그 디렉토리만은 보존하게 했다. 출처에
의존하지 않는 서술자로 해석하므로 나중에 다른 출처가 붙어도 소비자는 바뀌지 않는다.
확장 자산과 같은 메커니즘으로 정적 게시되어 CSS 내부 상대 url 도 해석되고, 파일을
고치면 그 변경을 감지해 재게시까지 예약된다.
FTP 접근이 없는 운영자에게는 그 자리도 없는 것과 같으므로 레이아웃 편집기에서 직접
넣고 고칠 수 있게 했다. 모듈·플러그인·템플릿이 한 엔드포인트를 공유한다 — 타입별로
나누면 같은 검증이 세 벌로 갈리고 그중 약한 하나가 우회로가 된다. 여기서 올린
스크립트는 그 레이아웃 한 장이 아니라 사이트 전 화면에서 실행되므로 레이아웃 편집과
분리된 전용 권한으로 연다. 운영자 CSS 가 화면을 조작 불능으로 만들면 그것을 고칠
화면에도 같은 CSS 가 실려 스스로 갇히므로, 서버가 목록을 비우는 탈출구(?custom=off)를
함께 뒀다.
동봉 자산은 재생성 경로에 버전 대조 가드를 붙였다. 선언과 다른 버전을 버전 디렉토리에
써 넣는 조용한 거짓말은 배포된 뒤에는 드러나지 않는다.
7.0.9 릴리즈 사전 점검에서 공개 배포물에 실릴 결함을 전수 정리한다.
출시일자: 이번 사이클에 버전이 오르거나 새로 추가된 대상 10건의 CHANGELOG
출시일을 실제 공개일로 정렬. 결제 3종은 직전 릴리즈 페이로드로 이미 나갔으므로
제외했다.
내부 역할 호칭: 공개 배포물 26파일 49곳을 중립 표현으로 치환. 이미 공개된
페이로드에는 실질 0건이라 이번 릴리즈가 첫 유입이었다.
최초 출시 규격: 신규 플러그인과 그 언어팩의 CHANGELOG 를 선례 규격으로
재구성. 작성 중 확인되지 않은 서술 2건은 코드 실측으로 교정했다.
번들 ja 언어팩: 번역 값에 남은 한글 40건 정정. 같은 용어가 세 갈래로 갈려
있던 표기도 함께 통일했다. 정정값의 근거는 저장소가 이미 갖고 있었다 —
테스트가 정답으로 단언하는 값과 배포물이 어긋난 상태였다.
재발 방지: 원인은 번역 생성기의 용어집 미등록이므로 출력만 고치면 다음
빌드에서 되살아난다. 용어집에 8건을 등록하고, 규정 3건과 잔존 검출 룰을
신설했다. 룰은 수정 전 배포물로 red 가 되는지를 픽스처로 고정해 판정기가
모집단에 닿는지를 증명한다.
비즈뿌리오 알림톡 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 재동기화로 기설치본의 소실
번역 자동 복구 (멱등·운영자 수정 보존·팩별 실패 격리)
템플릿 작성·검수·발송 기능의 실체는 전부 플러그인(sirsoft-message_bizppurio)
디렉토리에 있고 두 모듈 화면에는 주입만 되므로, 그 기능 서술은 플러그인
CHANGELOG 가 정합 위치다. 모듈 자신의 변경(통합 탭 선언 지원)을 기록한
Changed 항목만 남긴다.
공개 이슈 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 모드 오캐시 결함은 실패 테스트 선행 후 수정
- 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종,
버전·콘텐츠 무변경) 및 설치본 언어팩 동기
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 에 반영했다. 같은 증상을 다시 만났을 때의 진단 경로를
트러블슈팅 사례로 남겼다.
- 이커머스 「삭제된 PG」 항목에 @Tuwasduliebst 제보 attribution 부착
(제보 8/12 → 수정 8/14 — 같은 배치 제보 중 유일한 누락)
- 언어팩(ja) 5종의 공개 이슈 파생 번역 항목 11건에 원본 ko attribution 승계
( — core-ja/admin_basic-ja 기존 선례와 기준 통일)
- README 기여자 목록 변경 없음(신규 기여자 없음), ko↔ja 동기 검사 통과
KVE-2026-1914 S-2 게이트가 숨김(HIDDEN) 리뷰 이미지를 무조건 404 차단해,
관리자 리뷰 화면의 <img> 썸네일(인증 헤더를 실을 수 없는 렌더 경로)이 깨졌다.
게시판·페이지 첨부와 동일 설계로, 게이트를 통과한 관리자 응답의 직렬화
시점에만 30분 한시 서명 download URL 을 발급하고 서빙 엔드포인트가 유효
서명을 허용한다. 무서명·변조·만료 요청 게이트와 전시중 리뷰의 무서명
공개 URL(직접 URL/CDN 포함)은 종전과 동일하다.
숨김 리뷰가 이미지와 함께 직렬화되는 경로는 관리자 응답뿐이므로(공개
목록은 VISIBLE 필터, 작성 직후는 이미지 미로드) 서명 발급이 곧 게이트
통과 자격의 위임이다.
- 공개 릴리즈 누출 검사 error 3건 해소: 소스 주석의 내부 규정 파일명·내부 스크립트
경로 참조를 공개 문서 참조/도구 비귀속 표현으로 교체
- warn 4건 해소: 테스트·주석의 내부 역할 호칭을 "운영 실측 제보" 로 정리
- 릴리즈 스크립트(코어·확장)의 버전 태그를 공개 저장소 기존 태그 관례(v 접두사 없음)에
정합 — 접두사 혼재로 태그 시리즈가 갈라지는 것을 차단
- 공개 : MATCH 는 커버 인덱스가 있을 때만 조립 — 부재 시 LIKE 폴백 + 1회 경고,
카테고리 검색 예외를 categories_failed/search_failed 로 표면화하고 basic 템플릿이 오류 안내 렌더
- 공개 동근원: paginate page 명시 전달 (언어팩 check-updates, 상품 문의 목록)
- 공개 동근원: raw SQL 접두사/별칭 하드코딩 정리 (board 시더, 7.0.6 업그레이드 스텝,
결제 3플러그인 컨트롤러 51지점 모델 파생 전환)
- audit 룰 3종 신설 + repository-raw-hardcoded-table 컨트롤러 확대, 확장 TestCase
오토로더 중복 선언 가드 16지점, ja 언어팩 동기
공개 (@Tuwasduliebst 제보) 대응.
- ckeditor5: 미참조 이미지 정리 엔진 신설 — 참조 판정(hash + 파일명 2토큰,
filter_reference_sources 훅으로 확장 콘텐츠 등록) + 정리 커맨드(기본 꺼짐 옵트인,
3중 게이트) + 업로드 관리 화면(권한 분리·참조 배지·개별/선택 삭제) + 기설치본
설정 백필 upgrade step
- board: 임시 첨부 GC(상시) + 소프트삭제 첨부 영구 정리(옵트인) + 설정 UI,
저장 payload 누락(F4)·빈 temp 디렉토리 잔존(F5) 수정
- ecommerce: 임시 상품 이미지 GC + 카테고리 삭제 시 이미지 파일 미삭제(S4) 수정
- page: 임시 첨부 GC
- 코어: 고아 첨부 정리 커맨드(옵트인, site_logo 보호) + 사이트 로고 교체 시
구 로고 재편입 차단(S6) + DB 백업 미구현 501 정직화(B3) + 플러그인 관리자
메뉴 설치·업데이트 자동 동기화(F1·F7)
- 동반: 플러그인 설정 검증 오류 필드명 라벨화(F3), Toggle 노드 type 정정
수평 전개(marketing 1.0.2 bump·gdpr·ecommerce), ja 언어팩 4종, API 문서,
hooks.md, 시나리오 매니페스트 8종, Playwright E2E 4종
위임 관리자(부관리자)가 권한·역할·표현식·비밀 콘텐츠 경계를 우회하던
결함군을 계층 대칭성 원칙으로 전건 차단한다. 약한 경로가 정상 응답을
내보내는 것이 유일한 증상이라, 게이트를 생산 지점 한 곳(SSoT)에 두고
같은 데이터를 내보내는 소비 경로 전부가 그 게이트를 경유하도록 맞췄다.
- 등급 상한(rank ceiling): 슈퍼관리자 보호·역할/사용자 역할 배정(추가·제거
대칭)·일괄 상태변경·순서변경을 상세 경로와 동일 강도로 재적용. 가드는
DB 쓰기에 선행하여 거부 시 상태 불변.
- 레이아웃 표현식: new Function/with 실행을 AST 화이트리스트 평가기로 교체.
비-문자열 computed 키 정규화(normalizeKey)·Object facade(리플렉션 static
제거)·legacy 접근자 차단. 저장측 검증·정적 검사와 3계층 동형.
- secret 게이트: 비밀글의 댓글·첨부·문의 독립 경로 재적용, hash 파일서빙
소유권·비밀·발행 상태 검사 통일.
- 신뢰 스크립트 호스트: 확장 선언 기반 + same-origin 브라우저 정규화를
런타임·저장측·정적검사 3층 동형화.
- 회귀 감지: 단위·Feature·E2E·시나리오 매니페스트 전축 + audit 룰 4종 신설.
generic catch 가 4xx 를 돌려주면 인프라 장애가 입력 오류로 위장돼 장애 인지가
늦어지고, 이미 번역된 예외 메시지를 응답의 메시지 키 자리에 넘기면 키 해석에
실패해 원문이 그대로 화면에 나간다. 두 형태를 코어와 전 번들 확장에서 함께
정리하고, 판정기를 한 확장이 아닌 코어 모집단에 두어 확장 밖 동형 결함도
red 가 되게 했다 — 그 사각에 실제로 15건이 있었다.
주소록에서 해외 배송지를 고르면 국내 6필드만 옮겨 담아 해외 주소가 통째로
사라지던 결함도 함께 고쳤다. 저장은 200 으로 성공 처리돼 주문 상세를 다시
열기 전에는 드러나지 않았다.
확장이 훅으로 등록한 카탈로그에서 고른 값은 그 확장이 사라져도 저장값으로 남는다.
그 상태에서 값만 보고 판정하면 이미 제공 불가한 항목이 사용자 화면에 그대로 노출된다.
예외도 경고도 로그도 남지 않아 관리자 화면과 나란히 보지 않으면 드러나지 않는다.
- 결제수단에 지정한 PG, 현금영수증 발급사, 검색엔진 드라이버 세 축에 같은 판정을 적용.
공개 응답에서는 제거하고 관리자 응답에는 표시를 남긴다 — 운영자가 고쳐야 할 대상이라
감추면 복구 경로가 사라진다. 서버 검증도 같은 판정을 공유해 화면 우회 제출을 막는다.
- 설정 단건 저장이 벌크 저장과 다른 경로를 타던 문제를 코어·이커머스·게시판에서 정리.
저장은 성공하고 파생 값만 갱신되지 않아 어느 화면에서 저장했느냐로 결과가 갈렸다.
- 단건 저장의 값 형태 계약 신설. 빈 값으로 되돌릴 수 있게 하고, 타입은 defaults.json 의
기본값을 SSoT 로 삼는다. 해석 불가한 입력은 조용히 캐스팅하지 않고 거절한다.
- 드라이버 셀렉트를 서버 카탈로그에 바인딩하고, 저장값이 카탈로그에 없으면 그 값을
드러내는 안내를 8곳 전수에 붙인다. 종전에는 빈 칸으로만 보여 무엇이 저장됐는지
알 수 없었다.
시나리오 매니페스트 8종을 면제 없이 신설했다. `audit:allow` 는 cross product 와 effects
검사를 함께 끄므로, 면제가 걸린 매니페스트에 선언을 추가하면 검증이 회복되지 않는다.
그 아래에서 대응 테스트가 없는 effect 이름 2건이 살아남아 있었고, 함께 정리했다.
공개이슈 ··· 및 그 전수 해소분.
- 설정 저장·복원·초기화가 상주 프로세스 미러를 갱신하도록 단일 소유자화
- 만료 데이터 자동 정리 예약 12종 신설, 파기는 기본키 배치로 분할
- 회원 탈퇴를 전 경로 원자화하고 관리자 상태변경 경로를 정식 탈퇴로 통일
- 일괄 처리 목록의 선택을 화면에 보이는 행으로 한정(selectionScope)
- 비밀번호 정책 문구를 도메인 중립 라벨로 정정
- 정적 검사 2종·검증 스킬 설계 정합성 축 신설
StorageInterface::url 의 public 하드코딩을 완화하고 core.storage.filter_url 훅을
신설해, 완전 공개 자산(상품·카테고리·리뷰·에디터 이미지)의 직접 URL 서빙을 옵트인으로
열었다. 미설정 시 기존 스트리밍 100% 보존.
디스크 결정은 확장 개별 설정 > 코어 전역 > 미설정 순이며, 서빙·삭제·이동은 행에 기록된
disk 를 따라 전환 전후 자산이 혼재해도 각자 실제 저장 위치를 향한다. 고아 disk(공급
플러그인 비활성화)는 스트리밍으로 폴백해 500 이 되지 않는다.
공개 이슈 (@lyg-kaban 건의) 대응.
구간별 배송비의 종료값이 구간에 포함되지 않아 경계값이 무료배송으로
새고, 상품 옵션의 g/cm³ 저장값을 정책의 kg/L 로 환산하지 않아 금액이
1000배로 청구되던 문제를 수정한다.
- 구간 매칭을 종료값 오름차순 사다리로 교체 — 시작값은 표시 전용이
되어 기존 저장 데이터의 두 형태 모두에서 정확히 계산된다
- 단위 환산을 배송비 계산 한 지점으로 모으고, 부피무게와 실무게를
같은 kg 단위로 비교하도록 교정
- 계산이 조용히 0원이 되는 설정(구간 미등록·단위값/기준금액 누락·
중간 구간 무제한·계산 API 폴백 0원)을 저장 시점에 차단하고,
런타임 잔여 경로에는 경고 로그를 남긴다
- 연속성 규칙을 정책 타입별로 분리해 소수 구간(2.5kg) 저장을 허용
- 상품 옵션 무게/부피 응답 왕복, 주문 총 무게/부피 실값 기록
공개 제보(gnuboard/g7 @lyg-kaban): 관리자 쿠폰 폼의 「타 쿠폰과 중복 사용」
라디오를 클릭하면 자동바인딩이 DOM 문자열 "true"/"false" 를 폼 상태에 그대로
저장해 서버 boolean 규칙에서 422 로 저장이 실패했다. 표시 계층은 느슨 비교로
정상이라 저장 시점에야 드러나는 결함.
- 레이아웃: is_combinable 라디오 autoBinding 해제 + String 표시 바인딩
+ change 액션 === 'true' boolean 캐스팅
- 서버: Store/UpdateCouponRequest prepareForValidation 에서 문자열 표기 수용
boolean 정규화 (해석 불가값은 유지해 boolean 규칙이 422 처리)
- 게시판 is_secret 동일 잠재 위험 서버 방어 + User Store/UpdatePostRequest 의
Board 직접 조회 4곳을 Repository 경유로 교체 (board 1.0.4)
- 회귀: PHPUnit 11건(RED 선행) + 레이아웃 쓰기경로 타입 프로브 + E2E 왕복 spec
+ 시나리오 매니페스트(cases=32)
- 재발 차단: ·AGENTS.md 금지 패턴 + audit 룰
layout-boolean-option-autobinding 신설(전수 0건) + 형제 룰 4종
extensions/** glob 누락 보강 + 트러블슈팅 사례 8 + 회귀 테스트
공개 제보(리뷰 이미지에 filter_upload_file 부재)를 계기로 전 이미지 업로드
경로의 훅 트라이어드를 대칭화한다. 확장이 업로드 파일을 저장 전에 가로채
압축/변환할 수 있도록 하기 위함.
- 리뷰 이미지·CKEditor5 이미지 업로드에 filter_upload_file 필터 훅 추가
- 레이아웃 편집기 첨부 업로드에 훅 트라이어드(before/filter/after) 신설
- ckeditor5 1.0.2 버전 동기(manifest/package/composer/lock), 각 CHANGELOG 기재,
README 기여자 등재, hooks.md 업로드 트라이어드 및 필터 반환 계약 문서화
- 시나리오 매니페스트(upload-filter-hook-parity) + 3계층 훅 발화 테스트 추가
표시식이 selectedCount 를 fallback 없이 보간했다. 이 키는 체크박스 change
핸들러에서만 기록되므로 최초 마운트 구간에 undefined 이고, 엔진이 undefined 를
예외 없이 빈 문자열로 서식해 (/27) 로 보였다. 선택 상태의 SSoT 인 selectedItems
파생으로 교체해 주문 요약과 계산 방식을 일치시켰다.
같은 결함 클래스(초기값 없는 키를 옵셔널 없이 하위 접근) 28곳을 함께 방어하고,
3조건 동시 충족만 잡는 audit 룰로 codify 했다. 브라우저 실측(T9)에서 다운로드
이력 모달의 iteration 문자열 선언(매 렌더 TypeError)·미존재 아이콘명·정적 id
중복 3종을 추가로 발견해 정정했다.
공개 이슈: gnuboard/g7
Windows 는 하위 트리에 열린 핸들이 하나라도 있으면 디렉토리 rename 을 막는다.
잠금 프로세스를 찾아 종료하던 기존 대응은 디렉토리 핸들을 감지하지 못했고
사용 중인 편집기를 예고 없이 죽였다. rename 이 막히면 파일 단위 연산으로
폴백해 어떤 프로세스도 건드리지 않고 교체를 끝낸다. 커밋 전 점검에서
pint.json 이 코어 업데이트 대상에 빠져 있던 것도 함께 등재했다.
이커머스는 기본 제공 통화 삭제가 저장 응답에서 즉시 부활했다. 항목 단위
보충 병합이 "소실" 과 "의도적 삭제" 를 구분하지 못한 탓이라, 삭제 의도를
서버가 도출해 저장본에 기록하고 병합이 그 기록을 존중하게 했다. 그 통화로
결제된 과거 주문의 표기가 흔들리지 않도록 소수 자릿수 해석도 스냅샷 우선으로
바꿨다 — 금액은 원래 스냅샷 환율을 써 안전했으나 자릿수만 현재 설정을 봤다.
토스 결제수단의 PG 고정 선언( 전환)은 develop 의 선행 커밋이 이미 반영했다.
이 커밋은 그 전환에서 남은 뒷정리와, 같은 결함이 다시 나지 않게 하는 장치를 담는다.
AdjustEcommercePaymentMethodsLayoutListener 는 코어 레이아웃 표현식의 no-PG 리스트
리터럴을 정규식으로 재작성해 표시를 바꾸던 리스너인데, 에서 코어가 그 리터럴을
버리면서 매치 대상이 사라져 이미 사문화된 상태였다. 단위 테스트가 그 리터럴을 합성
레이아웃에 직접 넣어 검증한 탓에 계속 통과해 사문화가 드러나지 않았다. 리스너와 그
테스트, 시나리오 매니페스트의 관련 effects 를 함께 걷어낸다.
런타임 병합은 정의값으로 자가 치유되지만 저장된 주문설정 파일에는 pg_provider=null 이
그대로 남는다. 자기 접두사 수단만 정정하는 멱등 업그레이드 스텝을 추가했다.
능력 선언 규약이 어디에도 문서화돼 있지 않아 4개 PG 플러그인 중 토스만 어긋난 채
남았으므로, 규약을 명문화하고 미선언을 검출하는 audit 룰을 신설했다(수정 전 코드에
red 확인 후 전수 스캔 green).
1.0.0 이 공개 발행되었으므로 발행 섹션에 누적하지 않고 1.0.1 로 올렸다.
번들 언어팩은 코어 release 페이로드에 실려서만 공개되므로 그 팩의 공개 latest 는
직전 release 에 실린 버전이다. 그런데 버전 검사기가 lang-packs 를 대상에서 빼고 있어
이 축이 미검사로 남았고, 변경마다 bump 한 결과 공개된 적 없는 중간 버전이 최대 7단계까지
배포본에 쌓였다. 8개 팩의 버전을 규정상 한 단계로 되돌리고 그 사이 항목을 한 섹션에 병합했다.
항목 손실이 없음과 기공개 구간이 바뀌지 않음을 각각 실측했다.
7.0.6 과 함께 공개될 30건(코어·확장·언어팩)의 출시일을 2026-08-10 으로 맞췄다.
이미 공개된 버전의 날짜는 기록이므로 그대로 두었다.
재발을 막기 위해 검사기에 언어팩 축을 추가하고(기준선 origin/release) 회귀 테스트를 뒀다.
규정 문구의 "코어 검증으로 대체" 는 실제로 미검사를 뜻했으므로 기준선을 명시하도록 고쳤다.
7.0.6 에서 처음 번들되는 NHN KCP 휴대폰 본인확인 플러그인과 그 언어팩을 README 기본 제공
확장 표에 등재하고, 함께 어긋나 있던 번들 언어팩 개수 표기를 실제 수(16종)로 맞췄다.
prepare-release.sh 의 파일 본문 누출 검사가 error 10건으로 릴리즈를 차단하고 있었다.
공개 저장소는 를 제외하므로, 배포되는 파일이 그 경로나 를 참조하면
공개본에서 깨진 참조가 된다.
- 시나리오 매니페스트 4건: test_files 의 내부 하네스 테스트 경로 제거
- Playwright spec 3건: 룰 파일 경로/@see 포인터를 자기완결 서술로 교체
(@see 2건은 이미 stale — 가리키던 사례 번호가 실제와 달랐다)
- 소스/테스트 주석 3건: 파일명 노출 제거
내부 역할 호칭이 공개본에 영구 노출되는 warn 23건 중 21건도 함께 중립 표현으로
정정했다. API 표면 파일 2건은 주석만 고쳐도 문서 커버리지 게이트에 영구 면제가
필요해져 보류한다 — warn 은 릴리즈를 차단하지 않는다.
부수로 드러난 기존 결함 둘을 같은 세션에서 처리:
- gdpr Playwright config 에 locale 고정 누락 — 첫 로드가 en-US 로 나가 화면이 영어로
굳으면 한국어 문구를 단언하는 spec 이 전부 실패한다
- 언어팩 시나리오의 정적 검사 계층 전용 효과 2건을 effects 에서 rules_layer_coverage
로 이관 — 런타임 테스트로 성립하지 않는 항목이라 그 칸이 정합 위치다
검증: 누출 검사 error 0, audit --working 위반 0(룰 192), 시나리오 매니페스트 8건
errors 0, gdpr Vitest 148 green, PHP lint/JSON/YAML 정상.
버전 정합은 코어 working 7.0.6 / 공개 latest 7.0.5 = new-bump 로 릴리즈 가능 상태.
브랜치 통합 검증에서 정적 룰이 잡지 못한 결함 4건을 해소한다.
replaceState 후킹은 4개 결제 플러그인에 동일하게 적용됐는데 단위 회귀 테스트는
tosspayments 에만 있었다. 나머지 3개는 기존 injector 테스트가 있는데도 변경이
반영되지 않아, 앞으로 한 플러그인만 고쳐도 회귀를 잡을 수단이 없었다.
브랜드 마크 E2E 의 준비 게이트가 pg-locked-badge 만 세고 있었다. 그 배지는
pg_locked 인 수단에만 렌더되므로 PG 고정 수단이 없는 구성에서는 화면이 정상
렌더돼도 0 이 되어 타임아웃으로 오판 실패한다. 스펙이 선언한 "설치 구성을
하드코딩하지 않는다" 규율과 어긋나는 숨은 결합이라, PG 열의 상호배타 4분기
합계로 바꿔 구성과 무관하게 비고아 행 수와 일치시킨다. 읽히지 않던 badges
헬퍼도 함께 걷어낸다.
brand_mark 축과 두 효과가 매니페스트에 없어 마커가 가리킬 대상이 없었다.
축·효과·제외 규칙을 추가하며, 마커 파서가 쉼표로만 축을 분리한다는 사실을
확인해(× 는 첫 축만 잡힌다) 해당 spec 을 쉼표 형식으로 정정했다. 매니페스트를
건드리자 test_files 에 선언됐으나 마킹이 0건이던 파일 2건도 함께 드러나 마킹했다.
토스페이먼츠가 "확장 결제수단 1급화" 전환에서 통째로 빠져 있었다. 토스 결제수단은
그 전환 3일 전에 들어왔고, 전환 커밋은 nicepayments·nhnkcp·kginicis 만 건드렸다.
가 발견한 두 증상(브랜드 심벌 미노출 / PG 자유 선택)의 원인이 이 하나다.
토스페이먼츠
- 간편결제 5종에 brand_mark 를 선언한다. 같은 브랜드는 어느 PG 를 통하든 같은 배지여야
하므로 문자·색을 다른 PG 플러그인과 동일 값으로 맞췄다. 카드·가상계좌·계좌이체·휴대폰은
브랜드가 아니라 결제 형태이므로 키를 두지 않는다.
- defaults 에 pg_provider·pg_locked·needs_pg·refund_method 를 선언한다. 기존에는
pg_provider 가 null 이라 관리자 화면이 "PG 고정" 배지 대신 선택지가 하나도 없는 PG
셀렉트를 그렸고(토스 PG 는 자기 결제수단 id 를 supported_methods 로 선언하지 않는다),
서버 쪽으로도 PG 없는 결제수단으로 오인될 수 있었다.
- 관리자 브랜드 injector 를 신설한다. 관리자 레이아웃은 아이콘 열을 _cached_icon 하나로만
그리고 _cached_brand_mark 를 읽는 노드가 없어, 각 PG 플러그인이 자기 행의 아이콘을
배지로 치환하는 구조인데 토스에만 그 파일이 없었다.
4개 PG 플러그인 공통
- 환경설정 탭 전환은 pushState 가 아니라 replaceState 로 URL 만 바꾼다(탭 왕복 1회에
push 0 / replace 2 실측). pushState·popstate 만 후킹하던 injector 는 다른 탭에 갔다
돌아오면 행은 다시 렌더되는데 배지만 사라진 채 남았다. replaceState 후킹을 추가한다.
브라우저 실측(Chrome MCP 7대 축)으로 전 항목 확인했다. 탭 복귀 재주입은 수정 전
toss 0 / nicepay 0 / kginicis 0 → 수정 후 5 / 8 / 4 로 복원되는 것을 계측했다.
엔진
- dot notation setState(target:"_local.xxx")가 canonical _global._local 을 동기화하지
않아, 화면에는 선택 표시가 되는데 확장 커스텀 핸들러의 getLocal 에는 값이 보이지
않던 비대칭을 해소했다(engine-v1.58.2). 예외도 경고도 없이 값만 비어 발견이 늦다.
동기화 기준을 전체 스냅샷이 아니라 live _global._local + 변경 키로 잡아, 부분 상태가
base 가 되어 다른 키를 잃거나 앞선 setLocal 을 되돌리는 기존 회귀 경로를 피했다.
토스페이먼츠
- 간편결제 자체창 직행 지정을 top-level easyPay 로 넘겨 SDK 가 통째로 무시하던 것을
card.flowMode DIRECT + card.easyPay 정본 계약으로 교정했다.
이커머스
- defaults 에서 보충된 통화가 옛 is_default 를 들여와 기본 통화가 둘이 되면서 환율이
1.0 으로 박제돼 PG 청구액이 1/100 로 나갔다. 병합 직후 재동기화하고, 표시 계층의
기본 통화 해석을 default_currency 우선으로 통일해 환산 계층과 일치시켰다.
- 공급 확장이 더 이상 제공하지 않는 고아 결제수단이 주문서에 노출되던 것을 공개 API
단일 지점에서 차단했다. 관리자 응답은 운영자가 확인·삭제해야 하므로 그대로 둔다.
- 관리자 주문설정에서 Select 에 준 폭 클래스가 컴포넌트 기본 w-full 에 밀려 죽는
구조라, 폭 책임을 셀렉트에서 열 컨테이너로 옮겼다.
- 고아 행에서 마일리지 차감 시점 열만 가드가 빠져 노출되던 사전 결함을 함께 고쳤다.
열을 열거하는 대신 조상 체인의 가드 유무를 스캔해, 이후 추가되는 열도 자동으로
검사 대상이 되도록 회귀 테스트를 구성했다.
개발 도구
- dev-dashboard 인스톨러 초기화에 환경설정/첨부파일 삭제 토글을 추가했다. 컨테이너
디렉토리를 보존해 재생성 시 소유권이 바뀌지 않게 하고, 두 옵션이 같은 경로를 다뤄도
서로 간섭하지 않도록 분리했다.
규정
- 저장값과 확장 훅 카탈로그가 병합되는 설정에서 공개 응답이 카탈로그 소속까지 판정해야
한다는 규칙을 문서화하고, 정적 판정이 불가한 근거와 함께 coverage 에 등록했다.
게시판 게시글 반응 기능과 비즈뿌리오(카카오 알림톡·문자) 메시징 플러그인을 제거한다.
게시판 반응
- 마이그레이션 5종(반응 유형·반응·게시판 사용여부·활성 유형·게시글 카운트), 시더,
모델·저장소·서비스·컨트롤러·검증 규칙·예외·API 리소스 제거
- 관리자 게시판 폼/환경설정의 반응 사용 토글과 유형 선택 블록, 반응 유형 데이터소스 제거
- 사용자 게시글 상세의 반응 버튼 영역 제거 (반응 도입 이전 상태로 복원)
- 반응 관련 다국어 키(ko/en/ja), API 문서, 시나리오 매니페스트, 단위·기능·E2E 테스트 제거
비즈뿌리오 메시징 플러그인
- 플러그인 본체와 일본어 번들 언어팩 제거
- 코어 문서·빌드 스크립트·검사 baseline, 게시판·이커머스 CHANGELOG 에 남아 있던 참조 정리
존치 항목
- 게시판·이커머스 알림 설정 행 하단의 확장 슬롯(notification_definition_row_footer)은
코어 알림 설정 화면과 동일한 범용 확장점이라 유지한다
- 사용자 템플릿의 PostReactions 컴포넌트는 반응 기능 도입 이전부터 존재하던 자산이라 유지한다
- 태그 입력 드롭다운이 하단 고정 버튼에 가려지던 수정은 반응 기능과 무관해 유지한다
부수 정정
- 라우팅 판정 diff 스냅샷 총량을 실측값으로 갱신한다. 기록값 463 은 제거 이전 시점에도
실제(471)와 어긋나 있었고, 이번 제거 후 실측은 469 다.
7.0.6 사이클에서 유입된 회귀 3건을 출시 전에 닫는다. 추가옵션 저장소의
반환 타입 선언이 실제 반환(중첩 맵)과 어긋나 추가옵션 있는 상품의 담기·
바로구매가 죽었고, 검색 엔진이 결과 소비 시점에 SELECT 를 재작성해 정렬이
참조하던 스코어 별칭을 지웠으며, 미들웨어 targets 가 늘어난 라우트를
따라가지 못해 비회원 현금영수증이 전면 불능이었다. 셋 다 정적 검사의
사각지대였으므로 룰 2건과 계약 테스트를 함께 세워 재발을 막는다.
같은 유형의 잠복 결함 3건(빈 반환의 타입 불일치 2건, 없는 메서드 호출 1건)도
호출 경로가 생기는 순간 fatal 이므로 함께 닫았다.
브라우저 검수 중 드러난 선행 결함 5건을 이어서 수정한다. 엔진이 event 키로
선언한 액션을 React prop 으로 연결하지 않아 오류 없이 조용히 무반응이었고,
연결한 뒤에는 커스텀 컴포넌트의 이벤트 payload 가 유실됐다. 비회원 주문상세
응답에 현금영수증 키가 없어 발급 결과에 도달할 수 없었으며, 입금확인과
현금영수증 발급이 base 통화 금액을 써서 결제 통화가 다른 주문에서 각각
저장 실패와 잘못된 증빙을 냈다.
마지막으로 통화 단위를 코드·문구에서 걷어내 설정으로 이관한다. 다국어
문구의 원/円, 프론트의 KRW 고정표와 리터럴 폴백 173건, 서버 포맷의 통화
코드 리터럴이 대상이며, 기본 통화가 원이 아닌 상점에서 값은 맞고 단위만
틀린 금액이 예외 없이 나가던 문제였다. 통화 판정을 설정 단일 출처로 모으고
규칙 3건을 정적 검사로 고정했다.
스코프 검증 통과 직후·Post 락 획득 시점 사이에 게시글이 삭제되면
lockForUpdate 의 findOrFail 이 ModelNotFoundException 을 던지는데, 컨트롤러가
이 예외를 모르므로 일반 500 으로 새어나가 사용자가 "반응 처리에 실패했습니다"
라는 원인 불명 메시지만 보게 되던 문제를 수정. 이미 존재를 확인한 게시글이
사라진 것과 같은 의미이므로 PostNotFoundException 으로 변환해 404 로 일관 처리.
빠른 반응 전환 시 캐시된 reaction_counts 가 실제 board_reactions 행 수와
어긋나던 결함을 Post 락 직렬화 + 실제 COUNT 재집계 방식으로 수정. 반응
버튼에 aria-pressed/aria-disabled 를 추가해 스크린리더가 상태를 인지하도록
보완. 신규 게시판 생성 폼의 반응 유형 체크박스 초기값 누락, 본인 글 반응
클릭 시 안내 토스트 부재도 함께 수정.
게시판 설정 일괄 적용 화면의 대상 게시판 선택을 카드형으로 개선하고
"반응 사용" 필드 번역 키 누락(ko/en/ja)을 수정. TagInput 컴포넌트가
드롭다운 메뉴 포탈에 react-select 기본 z-index(1)를 그대로 둬 sticky
하단 버튼바에 가려지던 결함을 styles.menuPortal 오버라이드로 수정.
- 열람 권한 없는 비밀글에 추천/비추천을 남길 수 있던 결함을 서버(ReactionService)와
화면(반응 영역 미노출) 양쪽에서 차단. 신고 기능과 동일한 권한 판정 기준 재사용.
- 반응 버튼 UX를 다듬어 활성 상태는 색상으로만 표시하고, 클릭 순간에만 살짝 눌리는
촉각 피드백(active:scale-95)을 추가.
- 이슈 명세 재검토 중 describe.skip 상태였던 반응 E2E spec 에서 결함 3건 발견·수정:
대상 게시판/게시글이 실제로 반응 불가능한 대상이었던 점, 3단계(해제) 검증이 값
우연 일치로 거짓 통과 가능했던 점을 고치고 실제 실행으로 통과 확인.
Chrome MCP 검수 중 발견한 결함 수정 및 요청 반영.
- 게시글 상세 응답의 reaction_counts 가 배열로 붕괴되어 개수가 0으로
표시되던 문제 수정 (PostResource → stdClass 로 JSON 객체 보장) + 회귀 테스트
- 반응 버튼을 수정·삭제 버튼과 같은 줄에 배치
- 반응 UX 개선: 클릭 즉시 하이라이트 반영 + 개수는 응답값으로 갱신(전체
재조회 제거) + 처리 중 로딩·중복클릭 차단 + 실패 시 롤백·안내
- board.md 상세 응답 필드 + basic CHANGELOG + 시나리오 매니페스트 갱신
5단계 마무리 — 기능 동작 확인 후 마감.
- tests/scenarios/board-reaction.yaml: 단일 case 축 18조합 + effects 22개,
각 테스트에 @scenario/@effects 마킹 (test-scenario-coverage 통과)
- board-reaction-flow.spec.ts: 등록→전환→해제 E2E (describe.skip, 토큰 환경 해제)
+ reactionToken fixture
- 부수 테스트: react 활동 로그 기록, 새 게시판 반응 기본값 시드(확정 13)
- board/basic CHANGELOG Added 에 반응 기능 기재 (working 버전 누적, +2 아님)
ja 언어팩 동기화는 ANTHROPIC_API_KEY( 환경) 필요 — 후속 진행.
4단계 화면 3면 + 백엔드 수용.
- 게시글 상세(show.json): 신고 버튼 위에 반응 영역 — use_reaction &&
유형 존재 시 노출, 유형 iteration(아이콘+라벨+개수, 0도 노출), 본인 글 비활성화,
같은 유형 재클릭=해제·다른 유형=전환, 비로그인 안내 후 로그인 유도
- 관리 설정 기본값 탭 + 개별 게시판 편집 폼: 반응 사용 토글 + 유형 체크박스
(reactionTypes data_source iteration, active_reaction_types code 토글)
- FormRequest(Store/Update Board, Store/BulkApply Settings)에 use_reaction·
active_reaction_types 화이트리스트/캐스트/시드 추가 (미추가 시 토글 미저장)
- BoardResource.icon_name(fa-* 토큰) — Icon 컴포넌트 접두사 중복 방지
- ko/en 다국어 + boards/settings API 문서 갱신
- Vitest 10건(템플릿 4 + 모듈 6) green, board 관리/설정 87건 회귀 green
ja 언어팩·시나리오 매니페스트·E2E·버전 bump·CHANGELOG 는 5단계.
공개 이슈(gnuboard/g7) 17건 전수 대조에서 "진짜 누락"으로 판정된 5건을 해소한다.
— 서버가 만들어 내보내는 상점 주소가 각 지점에서 `/shop` 리터럴이나
`"/{$routePath}/..."` 조립으로 흩어져 있었다. 기본값이 아닌 상점에서는 그 주소가
존재하지 않는 화면을 가리키는데, 서버는 문자열을 만들어 내려보냈을 뿐이라 예외도
404 로그도 남지 않는다 — 링크만 조용히 죽는다. `ShopPathResolver` 를 단일 해석
지점으로 두고 주문 완료 이동·비회원 조회 안내·알림 메일·통합검색·상품문의·SEO
캐시·사이트맵 전 지점을 경유시켰다. 같은 값에 종속된 PG 4종 리다이렉트는
`{shopBase}` 자리표시자로, 편집기 상태 scope 는 선택 세그먼트 토큰 `/*?`
(engine-v1.58.0)로 해소했다. 기설치본은 업그레이드 스텝이 백필한다.
M-02 — 답변 깊이 상한이 config 는 1~10 인데 컬럼 comment 만 1~5 로 남아,
comment 에서 자동 생성되는 계약 문서 4곳이 실제보다 좁은 상한을 공개하고 있었다.
L-01 — 관리자 게시글 폼에 첨부 안내가 아예 없었고, 대신 사장된 고정 문구
("최대 5개 파일, 각 10MB")가 남아 있었다. 게시판마다 다른 실제 설정값을 렌더한다.
— 목록 1페이지가 공지 전량을 상한 없이 읽던 것에 안전상한을 두고(구조 무변경,
limit 부가만), 조회수 정렬 목록 술어를 덮는 복합 색인을 신설했다.
브라우저 실측 검수에서 발견한 사전 결함 1건(사용자 게시판 목록이 URL 정렬
파라미터를 데이터소스로 전달하지 않던 문제)도 함께 고쳤다. 폴백을 빈 문자열로 둬
URL 에 정렬이 없을 때 게시판 설정을 덮어쓰지 않게 했다.
develop 가 확장 결제수단 ID 허용을 위해 OrderPayment.payment_method 의
enum 캐스트를 제거했으나, 리베이스에서 텍스트 충돌이 없던 브랜치 소유 코드
4곳이 enum 전제 그대로 병합되어 string===enum(항상 false)·string 메서드 호출
(fatal)로 잠복했다. 부분취소/환불 재계산 fatal, 무통장 입금완료 현금영수증
자동발급 무동작, 토스 가상계좌 환불 수취계좌 미전송이 이에 해당하며, 전부
develop 기존 관용구(tryFrom/능력 메서드/->value)로 수렴해 해소.
IDV getStatus 의 리베이스 잔재 주석(코드와 모순)도 사실에 맞게 정정.
검증: ecommerce 235/235 · tosspayments 19/19 · pay_kginicis 5/5 green,
audit --working 0, 활성 반영(module/plugin:update --force) 완료.
develop 리베이스 완주 후 보류 항목 처리.
- ApiDocPipelineTest 의 예시값 갱신 단언을 병합 계약(타입 동일 시 보존 —
멱등)에 정합화. 예시값 최신성 단언과 멱등성 설계가 같은 상황에 정반대를
요구하던 stale test 로, 병합에서 의도 채택한 쪽은 멱등성이다.
- 환경설정 보안 탭 체크박스 2개의 label prop 을 Label 래핑+형제 Span 으로
교체. label prop 은 렌더되지 않아 설명 문구가 화면에 없었다.
- 확장 vite config 의 sourcemap: true 하드코딩이 --production 의
G7_BUILD_SOURCEMAP=0 주입을 조용히 무시해 배포본 dist 에 .map 과 dangling
참조가 남던 문제를 tosspayments·message_bizppurio 에서 정정하고 production
재빌드. template-security.md 에 게이트 형태를 명시하고 audit 룰
vite-sourcemap-env-gate(error) 를 신설해 재발을 차단한다.
- PHPUnit 12 대비: 접촉 테스트 파일의 docblock 메타데이터 6건 attribute 전환.
토스 주문서형 결제수단 도입으로 주문 body 표현식이 _computed.selectedPaymentMethod
→ selectedCorePaymentMethod (결제수단 id → core_payment_method 매핑) 로 바뀌었으나,
ecommerce 회귀 테스트의 context 헬퍼가 selectedPaymentMethod 만 세팅한 채 새 키를
누락해 payment_method 가 undefined 로 평가되던 stale test 를 정정. 레이아웃 로직은
정상이며 템플릿 측 테스트가 동일 동작을 이미 커버한다.