# TRACKB_GEMINI_FIX — PR #110 Gemini 리뷰 5건 수정

> PR #110 은 체크 11종 전부 SUCCESS. **Gemini 리뷰 5건 미해결만 머지를 막고 있다.**

## base / branch
- 저장소 **`/home/jay/projects/InsuRo`**
- **기존 브랜치 `task/task-2801-dev6` 에 이어서 커밋** (현재 head `f885c48`, main `657454f` 위로 rebase 완료)
- worktree 신규 생성. ⚠️ **rebase·force-push 하지 마라**

## expected_files
```yaml
allowed_resources:
  paths:
    - "server/routes/consultation_history_v1.py"
    - "server/schemas/consultation_history_v1.py"
    - "server/migrations/013_consultation_history_v1.sql"
    - "supabase/migrations/20260719120000_consultation_history_v1.sql"
    - "server/tests/test_consultation_history_v1.py"
  new_file_limit: 0
  commands: ["git","python3","pytest"]
  merge_policy: "none"
```
⚠️ `server/main.py`·`server/utils/legacy_write_guard.py`·`conftest.py` **수정 금지**(검증 완료분).

## 수정 요구 — Gemini 지적 5건

### ① ★ HIGH — `reference_id` 타입 불일치 (크래시 경로)
- **DB**: `server/migrations/013_*.sql:28` → `reference_id UUID NOT NULL`
- **Pydantic**: `server/schemas/consultation_history_v1.py:203` → `str = Field(min_length=1, max_length=128)`
→ 클라이언트가 `"customer-001"` 같은 **비-UUID 문자열**을 보내면 PostgreSQL `invalid input syntax for type uuid` → **500 크래시**.
**수정**: `reference_id` 를 **UUID 형식 검증**해 불일치 시 **`REFERENCE_SHAPE_INVALID` (400)** 반환.
- 스키마 레벨(`UUID` 타입) vs 라우터 레벨 검증 중 **어느 쪽이 적절한지 판단**하고 근거를 보고에 남길 것.
- ⚠️ 계약 §2-1 은 `reference_id: <string>` 이다. **UUID 강제가 계약과 충돌하지 않는지 확인**하고, 충돌하면 **STOP_REPORT**(계약 개정이 선행돼야 함).

### ② MEDIUM — insert 예외를 전부 409 로 뭉갬
`server/routes/consultation_history_v1.py:353` 부근이 `except Exception` 을 전부 `IDEMPOTENCY_CONFLICT`(409) 로 반환한다.
→ **DB 연결 실패·RLS 위반·스키마 불일치**도 409 가 되어 원인 파악 불가.
**수정**: **unique 제약 위반**(`duplicate key` 또는 PostgreSQL `23505`)인 경우에만 409. 그 외는 **500**.
- 실제 supabase 클라이언트가 던지는 예외에서 **에러코드를 어떻게 얻는지 실사**하고 근거를 남길 것.

### ③ MEDIUM — `granted_at` naive datetime
`schemas:172` `granted_at: datetime` → DB 는 `TIMESTAMPTZ`.
타임존 없는 값이 오면 **시간 왜곡** 가능.
**수정**: `AwareDatetime` 사용(파일 상단 `pydantic` import 에 추가).

### ④⑤ MEDIUM — 뷰 `SELECT *` (2파일 동일)
`server/migrations/013_*.sql:127`, `supabase/migrations/*.sql:127`
`CREATE OR REPLACE VIEW ... AS SELECT *` → 뷰 생성 시점 컬럼이 **고정**되어 이후 컬럼 추가가 반영되지 않고 오동작 위험.
**수정**: **필요 컬럼을 명시적으로 나열**. **두 파일을 동일하게** 수정할 것.

## 검증
- `python3 -m pytest server/tests -q -p no:randomly` → **758 passed 유지**(감소 0, 신규 실패 0)
- **①의 회귀 테스트 필수**: 비-UUID `reference_id`(예: `"customer-001"`) → **400 `REFERENCE_SHAPE_INVALID`**, 500 아님
- **②의 분기 테스트**: unique 위반 → 409 / 그 외 DB 오류 → 500
- **③**: naive datetime 거부 확인
- **④⑤**: 두 SQL 파일의 뷰 정의가 **동일**한지 확인
- **ANU 재실행 대상**

## ★ 절대 제약
- **PR 생성 0**(#110 이 이미 존재) · **main merge 0** · **rebase/force-push 0**
- **커밋 정확히 1개**. push 는 `git push origin HEAD:task/task-2801-dev6`
- **금지**: skip · xfail · assertion 완화 · `main.py`/`legacy_write_guard.py`/`conftest.py` 수정

## 봇 안전 프로토콜
- Edit·commit·push 직전마다 **cancel 마커 재확인**
- **`.done` 자동마커는 완료 증거가 아니다** — ANU 독립검증이 권위. 커밋·보고서 반드시 남길 것

## 보고
- `/home/jay/workspace/memory/reports/trackB-gemini-fix.md` (저장소 밖 · git stage 0)
- diff / 5건 각 조치 근거 / ①의 계약 정합성 판단 / ②의 에러코드 실사 결과 / **pytest 원문(전후)** / MATCH·GAP
- 봇 종료 전 ANU callback(envelope만·UTF-8 ≤3900B, collector=ANU key c119085addb0f8b7)

## goal_assertions (auto-generated)
- `python3 -m pytest server/tests -q -p no:randomly`
