허용목록이 플러그인 코드 상수라, 새 확장이 저장 키를 도입할 때마다 이 플러그인을
고쳐야 했다. 고치지 않으면 그 키는 방문마다 파기되는데 예외도 로그도 남지 않아
운영자에게는 "설정이 저장되지 않는다" 는 증상만 보인다.
허용목록을 운영자 설정(necessary_storage_allowlist)으로 옮기고, 관리자 환경설정에
브라우저 저장소·세션 저장소·쿠키 세 카드를 두어 직접 편집하게 했다. 확장은 GDPR 을
알 필요가 없고 GDPR 도 확장을 알 필요가 없다 — 연결은 운영자가 화면에서 한다.
저장 키를 플러그인이 관측·수집하지 않는 것도 같은 이유다: 관측 자체가 추적이다.
판정은 서버(미들웨어)와 클라이언트 셋(인터셉터 둘 + 정리기)이 같은 설정을 같은 매칭
규칙으로 읽는다. 잠금 항목(로그인 토큰·CSRF·세션 쿠키·동의 기록)만 설정 밖에 두고
판정 시점에 합집합으로 얹는다 — 설정에 담기면 저장 요청 한 번으로 지워져 잠금이
아니게 된다. 기설치본은 업그레이드 스텝이 현재 카탈로그를 설정 파일에 못박되,
운영자가 이미 편집했으면 그대로 둔다.
함께 고친 선재 결함 셋:
- 차단 도메인 추천 목록이 응답에 실리지 않아 자동완성이 동작하지 않던 문제
- 세션 쿠키 이름을 기본값에서 바꾼 사이트에서 브라우저 측 목록의 그 항목이 죽던 문제
- 쿠키 목록에만 앞부분 매칭(`이름_*`)이 적용되지 않던 문제
공개 (@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종
동의 이력과 정책 버전 발행 이력의 페이저가 마지막 페이지 번호 하나에 의존하고
있었다. 총 건수를 끝까지 세지 못한 목록에서는 그 값이 없어, 페이저 노출 조건이
거짓이 되어 통째로 사라지거나 "다음" 이 첫 페이지부터 비활성이었다.
마지막 페이지를 아는 경우의 동작은 종전과 같고, 모르는 경우에만 다음 페이지
존재 여부로 판정한다. 표시용 마지막 페이지 번호는 지어내지 않는다.
develop 리베이스 3커밋이 각자 정상인데 합쳐지면서 어긋난 지점들을 정리한다.
- 발송 이력 목록이 뒤 페이지로 갈수록 느려지고 같은 시각 발송분이 중복
노출되던 두 결함을 코어 지연 조인으로 함께 닫았다. 이 파일은 develop 쪽에서
들어와 492 브랜치에서는 검출될 수 없었다.
- 정렬 허용 컬럼·지연 조인 호출 계약 테스트가 순수 소스 스캔인데도 앱을 부팅해
케이스마다 DB 연결을 잡았다. 스캔 대상이 늘자 연결 상한(151)을 넘겨 실패했고,
앱 의존이 없으므로 부팅을 뺐다.
- 확장 업데이트 모달 테스트는 stub 이 모든 체크박스에 같은 식별자를 붙여,
검색 인덱스 재생성 체크박스가 추가되자 대상을 특정하지 못했다.
- 동의 이력 필터 어휘가 enum 전 케이스로 넓어진 것을 테스트 기대값에 반영하고,
이력 페이지네이션 버튼의 액션 구조를 나머지와 같은 형태로 통일했다.
- 관리자 확장 화면의 존재 확인 가드가 추가된 뒤 갱신되지 않은 mock 을 맞췄다.
다크 모드 대비가 빠진 버튼 둘을 저장소 관례에 맞추고, 사용자 템플릿에서
그 클래스가 실제 CSS 로 생성되도록 safelist 를 함께 채웠다.
목록 조회 성능 축(깊은 OFFSET·정렬·색인)과 그 검증 계층에서 계획서 전수검수와 3회에 걸친
감사가 지적한 항목을 처리했다. 세부 경위는 의 각 회차 문서에 있다.
검증 계층 — 컨트롤러가 base Request 를 직접 주입받던 확장 13곳을 전용 FormRequest 로 옮겼다.
옮기면서 기존 동작 계약은 그대로 두었다: 상한 초과 limit 을 거부하지 않고 상한까지 반환하던
공개 API, per_page 를 범위로 조정하던 관리자 목록, 미지원 period 를 year 로 해석하던 인기글
목록 모두 종전과 같은 응답을 낸다. 상한/폴백을 rules 로 승격시키면 200 이던 응답이 422 가
되어 기존 링크가 깨지므로, 규칙은 타입만 닫고 클램프·폴백은 접근자가 맡는다. period 는
접근자가 닫힌 집합만 반환해 캐시 키 공간도 함께 닫힌다.
ckeditor5 이미지 업로드만 ResponseHelper 봉투를 쓰지 않는다. 응답을 파싱하는 주체가 CDN 으로
로드되는 상위 CKEditor5 43.3.1 의 SimpleUploadAdapter 라 규약을 바꿀 수 없어, 각 응답 지점에
사유를 명시한 면제를 부착하고 근거를 API 문서에 남겼다.
하네스 — 룰 5개의 대상 경로 패턴이 매처와 맞지 않아 번들 확장 컨트롤러가 검사 대상에서
통째로 빠져 있었다. 패턴을 고치자 확장 위반 17건이 드러나 전건 처리했다. severity 오타가
요약 집계 양쪽에 안 잡혀 "0 error" 로 보고되던 문제도 런너 사전 검증으로 막았다.
정렬 게이트 대조 하네스는 관계 정렬 변형만 쓰는 저장소를 탐지하지 못한 채 통과시키고 있었다.
탐지·제외·인자 파싱을 함께 고치고 단위 테스트를 신설했다.
PR 전 마지막 재검토에서 남겨뒀던 두 항목을 처리한다.
- 게스트 세션 쿠키 HMAC 서명에 만료시각을 추가했다. 결제 플러그인
(IssuesReceiptCookie)과 동일하게 값 형식을 {uuid}|{만료시각}|{서명}
3단 구조로 바꾸고, 서명 자체가 만료시각도 함께 해시하므로 만료시각만
위조해 유효기간을 늘리는 시도도 차단된다. 만료 기간은 쿠키 자체의
브라우저 만료(1년)와 동일하게 맞췄다 — 결제 정보가 아닌 쿠키 선호도
식별자라 짧게 잘라 잦은 재발급을 강제할 실익이 없다.
- 관리자 설정 화면의 정책 버전 이력 토글 버튼에서 sequence handler의
actions 배열이 params 안에 잘못 중첩되어 있던 걸 발견해 바로잡았다.
엔진(ActionDispatcher.handleSequence)이 두 위치를 모두 인식하는
fallback을 갖고 있어 실제 동작은 정상이었지만, 정석 위치(top-level)로
정리하고 실제 클릭 시 이력 표가 펼쳐지는지 검증하는 E2E를 추가했다.
가 GDPR 관리자 설정 화면 스크린샷에서 카드 제목만 다른 확장과 달리
빨간색으로 표시되는 것을 발견해 지시했다.
「운영 주체」·「쿠키 동의 배너」·「자동 차단 정책」 카드 제목과 차단
도메인 안내 소제목이 에러/경고 전용 시맨틱(text-error-strong, red 계열)을
잘못 사용하고 있었다. 일반 카드 제목이므로 다른 정상 카드와 동일한
중립 톤(section-heading-md)으로 교체.
원래 develop 에 이미 있던 기존 결함이며 다른 확장(marketing,
pay_kginicis 등)에도 동일 패턴이 있으나, 이번엔 GDPR 플러그인 범위로
한정해 수정한다.
기존 Vitest 회귀 가드가 이 색상 버그를 "의도된 설계"로 잘못 확정해두고
있어 함께 뒤집었고, 실제 브라우저에서 색상을 검증하는 E2E 테스트도
추가했다(computed style RGB 값 검사).
이슈 체크리스트와는 별개로, 처리 완료 후 지시로 진행한
sirsoft-gdpr 플러그인 전수 비판적 검토에서 발견한 보안·결함 3건을
수정한다.
- Admin 설정 저장 API 의 검증 우회 fallback(빈 요청 시 $request->all
사용) 제거. UpdateAdminSettingsRequest 필드가 모두 nullable 이라
검증을 거치지 않은 임의 키가 저장 로직까지 전달될 수 있었다.
- 게스트 세션 식별 쿠키(gdpr_session) 에 HMAC-SHA256 서명 적용.
api 미들웨어 그룹에는 EncryptCookies 가 없어 쿠키가 평문으로 오가
임의 UUID로 타인의 게스트 동의 상태를 조회/철회할 수 있었다.
결제 플러그인들의 IssuesReceiptCookie 트레이트와 동일 컨벤션 채택.
이 조치로 배포 이전 발급된 비회원 쿠키는 1회 초기화되며 이미
배너를 닫았던 비회원은 다음 방문 시 배너를 다시 보게 된다(회원
동의 이력은 영향 없음) — CHANGELOG 에 고지.
- 게스트로 쿠키 배너를 닫은 뒤 동의 이력 없는 다른 계정으로 로그인해도
배너가 계속 숨겨져 있던 결함 수정. _global.gdprBannerDismissedFor 가
"닫힘 여부"(boolean) 대신 "누가 닫았는지"(사용자 식별자)를 저장하도록
변경해, 로그인으로 사용자가 바뀌면 다시 노출되게 한다. 실제 로그인
폼 제출을 거쳐 재현하는 E2E spec 신규 작성(PlaywrightSeedGdprGuestLogin
시드 커맨드 포함, sirsoft-page 의 PlaywrightSeedPage 패턴 재사용).
부수: 자동 차단 정책 안내에 보호 범위 한계 고지 추가, GDPR 플러그인
번들 로딩 우선순위 상향(다른 확장의 스크립트로부터 보호 범위 확대).
banner_enabled(쿠키 배너 노출) 토글 안내가 "마이페이지 동의 관리 카드"까지
함께 켜지고 꺼지는 것처럼 서술되어 있었으나, 실제로는 카드가 이 토글과
무관하게 동의/철회 이력이 있는 회원에게 항상 노출된다(GDPR Art.7(3) 철회
대칭성 보장, mypage_privacy_tab.json 회귀 가드로 이미 고정된 설계).
문구만 실제 동작과 어긋나 있어 ko/en 양쪽 hint 및 관련 코드 주석을
바로잡았다.
문구 확인 과정에서 field_legal_entity_name / field_data_storage_location /
field_banner_enabled / field_banner_position 4개 필드가 텍스트 스타일
전용 클래스(section-heading-md, grid 미정의)를 컨테이너로 잘못 사용해
안내 문구가 길어지면 입력/토글 컨트롤이 아래 줄로 밀려나던 기존 UI
결함도 함께 발견해 수정했다. 같은 파일의 field_privacy_policy_slug가
이미 쓰던 올바른 grid-3col-responsive 패턴으로 통일.
정책 버전 snapshot 모달의 본문 페이지 링크가 /{{slug}} 로 조합되어
페이지 모듈(sirsoft-page) URL 패턴 /page/{slug} 와 불일치해 404가
발생하던 문제를 수정. 쿠키 배너의 동일 링크와 조합 방식을 통일했다.
회귀 검증을 위해 GDPR 플러그인에 Playwright E2E 인프라를 최초 도입.
- cookie_categories_rows / blocked_domains_taginputs iteration 컨테이너의 정적 id를
index_var(categoryIdx)로 동적화 — 카테고리가 여러 개일 때 동일 HTML id가 중복 렌더되던
W3C id 유일성 위반 수정 (audit layout-iteration-static-id)
- 카테고리 「필수」 배지 dark:bg-red-800 / text-danger-soft 클래스 사이 공백 누락으로
다크 모드 배경·글자색이 미적용되던 오타 수정
이슈 작업 중 audit-branch 전수 검사에서 발견한 기존 결함 (이번 이슈 기능과 무관, )