fix(gdpr,hooks): 동의 출처 어휘 정정과 확장 문서 강제의 Codex 트리 이식
쿠키 동의 저장 요청이 서버만 기록하는 출처(가입 시 동의)를 지정할 수 있었다. 주석은 지정 불가라고 적혀 있었고 코드가 그것을 잃은 쪽이었다 — 그 값을 쓰는 곳은 회원가입 리스너뿐이고, 받는 경로는 비인증 방문자도 도달한다. 형제 값 둘이 이미 같은 이유로 막혀 있어 대칭을 회복한다. 확장 문서 동반 강제가 두 도구 트리 중 한쪽에만 있었다. 다른 쪽으로 작업하면 문서를 빠뜨려도 아무 경고가 없고, 그 결과는 이상 0건과 구분되지 않는다. 룰· coverage·편집 시점 안내·세션 종료 검사·미채움 기준선을 이식하고, 두 사본이 같은 입력에 같은 판정을 내는지를 픽스처가 한 곳에서 단언하게 했다.
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
### Fixed
|
||||
|
||||
- 회원탈퇴로 자동 철회된 동의 이력이 관리자 「GDPR 동의 이력」 화면의 출처 필터로 걸러지지 않던 문제를 수정했습니다.
|
||||
- 쿠키 동의 저장 요청이 서버만 기록해야 하는 출처(회원가입 시 동의)를 직접 지정할 수 있던 문제를 수정했습니다 — 동의 이력의 출처가 실제 동의 경로와 일치합니다.
|
||||
|
||||
## [1.0.3] - 2026-08-19
|
||||
|
||||
|
||||
@@ -83,6 +83,18 @@ case입니다 — 두 지점 모두 enum이 아닌 `'withdraw'` 리터럴을 직
|
||||
추가로 정정했습니다. 새 기록 지점을 추가할 때 위치 인자로 리터럴을 넘기면 이 가드가 여전히
|
||||
못 볼 수 있다는 점을 유의하세요 — 가능하면 `'source' =>`/`'last_source' =>` 형태(배열 키)를
|
||||
쓰거나 이 테스트의 정규식을 함께 넓힙니다.
|
||||
|
||||
전체 어휘(`ConsentSource::allValues()`)와 **공개 요청이 지정할 수 있는 부분집합**
|
||||
(`ConsentSource::requestSelectableValues()`)은 다릅니다. `register`(회원가입 시 동의) ·
|
||||
`mypage_renew_all`(정책 개정 후 일괄 재동의) · `withdraw`(회원탈퇴 시 일괄 철회)는 서버가
|
||||
스스로 기록하는 경로이므로 `StoreCookieConsentRequest` 의 `Rule::in` 에서 제외됩니다 —
|
||||
이 엔드포인트는 `optional.sanctum` 이라 비인증 방문자도 도달하므로, 공개 요청이 이 값을
|
||||
실을 수 있으면 가입하지도 탈퇴하지도 재동의하지도 않은 사람의 이력이 그렇게 기록됩니다.
|
||||
동의 이력은 출처가 존재 이유이고, 그렇게 기록되어도 오류도 로그도 남지 않습니다. 반대로 관리자
|
||||
동의 이력 화면의 출처 필터(`IndexConsentLogRequest`)는 `allValues()` 를 씁니다: 기록된
|
||||
어휘 전부가 필터로 도달 가능해야 하기 때문입니다. 새 case 를 추가할 때 어느 쪽에 속하는지
|
||||
판단하고, 제외한다면 `ConsentSourceVocabularyParityTest` 에 제외 단언을 함께 남기세요 —
|
||||
목록에서 빠뜨려도 단언이 없으면 아무 테스트도 red 가 되지 않습니다.
|
||||
<!-- @intent END -->
|
||||
|
||||
## Repository
|
||||
|
||||
@@ -51,8 +51,15 @@ enum ConsentSource: string
|
||||
/**
|
||||
* 사용자 요청으로 직접 지정할 수 있는 출처 값 목록.
|
||||
*
|
||||
* `register` / `mypage_renew_all` 은 서버가 스스로 기록하는 경로이므로
|
||||
* 공개 요청 본문에서 지정할 수 없습니다.
|
||||
* `register`(회원가입 시 동의) · `mypage_renew_all`(정책 개정 후 일괄 재동의) ·
|
||||
* `withdraw`(회원탈퇴 시 일괄 철회) 는 서버가 스스로 기록하는 경로이므로 공개 요청
|
||||
* 본문에서 지정할 수 없습니다. 이 엔드포인트는 비인증 방문자도 도달하므로, 지정을
|
||||
* 허용하면 가입·재동의·탈퇴를 하지 않은 사람의 이력이 그렇게 기록됩니다 — 동의 이력은
|
||||
* 출처가 존재 이유이고, 그렇게 기록되어도 오류도 로그도 남지 않습니다.
|
||||
*
|
||||
* 새 case 를 추가할 때는 그것이 공개 요청으로 지정 가능한지 판단해 이 목록에 넣거나
|
||||
* 빼고, 뺐다면 `ConsentSourceVocabularyParityTest` 에 제외 단언을 함께 추가합니다 —
|
||||
* 목록에서 빠뜨려도 검증이 없으면 아무 테스트도 red 가 되지 않습니다.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
@@ -61,7 +68,6 @@ enum ConsentSource: string
|
||||
return [
|
||||
self::Banner->value,
|
||||
self::PreferenceCenter->value,
|
||||
self::Register->value,
|
||||
self::Mypage->value,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -183,6 +183,13 @@ class ConsentSourceVocabularyParityTest extends TestCase
|
||||
$selectable = ConsentSource::requestSelectableValues();
|
||||
|
||||
$this->assertNotContains(ConsentSource::MypageRenewAll->value, $selectable);
|
||||
// 회원탈퇴 철회는 `GdprConsentService::revokeAllOnWithdraw()` 만 기록하는 경로다.
|
||||
// 공개 요청이 이 값을 실을 수 있으면 탈퇴하지 않은 사용자의 이력이 탈퇴로 기록된다.
|
||||
$this->assertNotContains(ConsentSource::Withdraw->value, $selectable);
|
||||
// 가입 동의는 `GdprAuthConsentListener::recordRegisterConsents()` 만 기록하는
|
||||
// 경로다. 이 엔드포인트는 비인증 방문자도 도달하므로, 지정을 허용하면 가입하지
|
||||
// 않은 방문자의 이력이 가입 동의로 기록된다.
|
||||
$this->assertNotContains(ConsentSource::Register->value, $selectable);
|
||||
$this->assertContains(ConsentSource::Banner->value, $selectable);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user