# task-2087 완료 보고서: Sanitize 게이트 — 외부 AI 호출 전 PII 자동 마스킹

## SCQA

**S**: `codex_gate_check.py`에서 Codex companion 호출 시 프롬프트에 설계 문서와 코드 내용이 포함되어 외부 AI로 전송된다. `utils/sanitize_gate.py`에 PII 마스킹 함수(`sanitize_text()`)가 이미 존재한다.

**C**: 그러나 sanitize_gate가 자동 호출되지 않아, 프롬프트에 주민번호/전화번호/API 키 등 PII가 포함될 경우 외부 AI에 그대로 전달되는 보안 위험이 있었다. task-2080 Q-3에서 지적된 문제.

**Q**: `_run_codex_companion()` 호출 전에 `sanitize_text()`를 자동 적용하여 PII 유출을 방지할 수 있는가?

**A**: `codex_gate_check.py`의 프롬프트 조합 후, Codex 호출 직전에 `sanitize_text()`를 자동 적용하는 코드를 삽입했다. import 실패 시 noop fallback으로 원본 전달 + 경고 로그. sanitize_text 예외 시에도 try/except로 안전하게 처리. pytest 42건 전체 통과 (기존 39 + 신규 3).

## 수정 파일

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/codex_gate_check.py:19-27 | sanitize_gate import (try/except + noop fallback) | grep "_SANITIZE_AVAILABLE" OK (2건) | verified |
| scripts/codex_gate_check.py:341-349 | _run_codex_companion 호출 전 PII 마스킹 + 예외 처리 | grep "PII 마스킹" OK (1건) | verified |
| scripts/codex_gate_check.py:18 | sys.path에 workspace root 추가 (import 안정화) | grep "sys.path" OK (1건) | verified |
| scripts/tests/test_codex_gate_check.py:868-946 | TestSanitizeGateIntegration 클래스 (3개 테스트) | grep "TestSanitizeGateIntegration" OK (1건) | verified |

## 테스트 결과

- pytest 42/42 PASS (0.16s)
- 기존 테스트 39건: 회귀 0건
- 신규 테스트 3건:
  - `test_pii_in_prompt_is_masked_before_codex_call`: PII(전화번호/주민번호) 마스킹 후 Codex 전달 확인
  - `test_sanitize_unavailable_still_works`: import 실패 시에도 정상 동작 확인
  - `test_no_pii_no_masking_log`: PII 없는 프롬프트에서 gate PASS 확인

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **sanitize_text 예외 시 전체 gate 중단 위험** — try/except로 감싸고 예외 시 원본 전달 + 경고 로그
   - 상세: codex_gate_check.py:343-348 try/except 블록 추가
2. **scripts/ 디렉토리에서 직접 실행 시 utils.sanitize_gate import 실패** — sys.path에 workspace root 자동 추가
   - 상세: codex_gate_check.py:17-18 `sys.path.insert(0, ...)`
3. **pyright 타입 경고 (_sanitize_text possibly unbound)** — noop callable fallback 함수로 해결
   - 상세: codex_gate_check.py:19-20 `_sanitize_text_noop` 함수 정의

### 범위 외 미해결 (2건)
1. **test_codex_gate_check.py L787 "args" not accessed** — 기존 코드(task-2076 TestSubprocessEnvPassing). 범위 외 사유: 다른 task에서 작성된 기존 테스트
2. **test_codex_gate_check.py L798 import 미해결** — 기존 코드(task-2076). 범위 외 사유: pyright 분석 경로 이슈 (런타임 정상)

## L1 스모크테스트 결과

- 서버 재시작: 해당없음 (subprocess/정제 작업)
- API 응답 확인: `codex_gate_check()` 실제 호출 → Codex companion 정상 응답, source="codex_companion", pass=true, risks=3건(critical 0건)
- 스크린샷: 해당없음

## 모델 사용 기록

- 팀원: 루(Lugh) / 작업: codex_gate_check.py sanitize 코드 삽입 / 사용 모델: sonnet
- 팀원: 모리건(Morrigan) / 작업: sanitize 통합 테스트 작성 / 사용 모델: sonnet
- 팀장: 다그다(Dagda) / 작업: 이슈 해결(예외 처리, sys.path, pyright), 검증, 보고서 / 사용 모델: opus

## 셀프 QC 체크리스트

- [x] 1. 영향 파일: codex_gate_check.py (sanitize_gate.py는 읽기만)
- [x] 2. 엣지 케이스: import 실패, sanitize_text 예외, PII 없는 프롬프트 — 모두 테스트 커버
- [x] 3. 작업 지시와 일치: sanitize_text 자동 호출, import 실패 시 원본 전달 + 경고
- [x] 4. 에러 처리/보안: try/except 적용, fail-open 경고 로그
- [x] 5. 테스트 커버리지: 3개 시나리오 커버 (PII 마스킹, import 실패, PII 없음)
- [x] 6. 이슈 전부 해결: 3건 자체 해결, 2건 범위 외
- [x] 7. 코드 아키텍처: SOLID/DRY 위반 없음
- [x] 8. 인터페이스 변경 없음 (내부 로직만 추가)
- [x] 13. L1 스모크테스트: 실제 codex_gate_check() 호출 확인

## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회

