# task-2991 (초안 — 회장 승인 대기) InsuRo 동의 게이트 완전성 + Realtime 구독 감사

## 배경
task-2990(PR #239, main=`d0987089`)이 `AuthGuard` 라우트 게이트를 세웠으나 **완전하지 않다.**
ANU 직접 재현: `src/App.tsx` 에서 `<ChatNotificationListener />` 가 `<AuthGuard>` 의 **형제**로
마운트되어 세션만으로 동작한다. 동의 인터스티셜이 떠 있는 동안에도 고객명 + 메시지 60자
토스트가 렌더될 수 있다. task-2990 명세가 `App.tsx` 를 forbidden_paths 로 묶었기 때문에
구조상 손댈 수 없었다 — 봇 판단은 정당했다.

## 범위 (2건)

### A. 동의 게이트 완전성 (MEDIUM)
`ChatNotificationListener` 가 세션뿐 아니라 **유효 동의**까지 확인하도록 한다.
- `hasValidPrivacyConsent` 는 이미 `@/components/AuthGuard` 에서 export 되어 있다. 재사용할 것.
- 권장: `App.tsx` 에서 `<AuthGuard>` 안으로 옮기기보다, 리스너 자체가 동의를 확인하게 한다
  (라우트 전환마다 재구독되는 부작용 회피). **둘 중 무엇이 단순한지 먼저 판단하고 근거를 남길 것.**
- `onAuthStateChange` 의 `USER_UPDATED` 로 동의 직후 구독이 정상 개시되는지 반드시 검증.

### B. Realtime 구독 RLS 감사 (등급 미정 — 감사 결과로 확정)
`ChatNotificationListener` 는 `conversation_messages` INSERT 를 **filter 없이 전량 구독**한 뒤
클라이언트에서 `conv.agent_id !== userId` 로 거른다. Realtime RLS 가 약하면 **타 상담원의
메시지 payload 가 브라우저까지 도달**한다. task-2990 에서 검증하지 않았다.
- Supabase Realtime 의 `conversation_messages` 발행 정책과 RLS 를 **실측**할 것.
- 도달한다면 서버측 filter 또는 RLS 강화. **추정 금지 — 실제 payload 를 관측해 판정.**
- 연관: task-2985(익명 상담내용 열람 CRITICAL, 회장대기)와 같은 테이블이다. **중복 조치 주의.**

## 하지 말 것
- `user_metadata` 를 보안 경계로 취급하는 코드 추가 금지. 이것은 **동의 절차 집행**용이다.
  서버측 영속화는 별건(B 배치 DDL)이다.
- task-2990 이 세운 게이트 로직 재작성 금지. 재사용만 한다.

## 완료 조건
A: 동의 미완료 세션에서 토스트 미노출을 **실브라우저로 재현** · 동의 후 정상 동작 확인
B: Realtime payload 도달 여부 **실측 증거**(관측 로그) 첨부 · 도달 시 차단까지
공통: 회귀 유지(기준선 main `d0987089` 실측치 사용 — **명세 수치 신뢰 금지**) · build 0 · CI GREEN
**PR 생성까지가 범위. 머지는 ANU.**

## 참고
- ANU 판정 근거: `memory/events/task-2990.anu-override.json`
- 선행 보고서: `memory/reports/task-2990.md`
