# [Lv.1 hotfix] 소식지 검토 상세뷰 크래시 수정 — source_file_ref 객체 렌더 (React #31)

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "src/components/newsletter/ReviewDetailPanel.tsx"
    - "src/components/newsletter/reviewApi.ts"
    - "src/components/newsletter/ReviewDetailPanel.test.tsx"
  forbidden_paths:
    - ".github/**"
    - "extension/**"
    - "server/**"
  commands: ["npm","npx","vite","git"]
  merge_policy: "none"
  ttl_hours: 8
```
> ★ base=현 origin/main(2ea5096, 배포됨). 라이브 핫픽스. 근거: 회장 실제 클릭 테스트에서 상세뷰 크래시 재현.

## 배경 (실측 확정)
관리자 검토 화면에서 소식지 한 건을 클릭하면 상세뷰가 **React 최소화 에러 #31**("Objects are not valid as a React child, object with keys {sha256, file_url}")로 크래시. 원인:
- 백엔드(`server/routes/newsletter_review_v1.py:137`)는 `source_file_ref` 를 **객체** `{"file_url": ..., "sha256": ...}` 로 반환(jsonb).
- 프론트(`reviewApi.ts:55`)는 `source_file_ref: string | null` 로 **문자열로 오인**하고, `ReviewDetailPanel.tsx:128` 에서 `{detail.source_file_ref}` 로 **객체를 그대로 렌더** → 크래시.

또한 좌측 "원문" pane 설계 전제(source_file_ref = 원문 텍스트)가 틀렸다 — source_file_ref 는 **원본 파일 참조**(url+sha)이지 원문 텍스트가 아니다. 진짜 원문 = 원본 파일 자체.

## 작업 (surgical)
1. **타입 수정** (`reviewApi.ts`): `source_file_ref: { file_url?: string; sha256?: string } | null` (또는 적절한 인터페이스). string 가정 제거.
2. **크래시 제거 + 원본 파일 표시** (`ReviewDetailPanel.tsx` 좌측 "원문" pane):
   - 객체를 그대로 렌더하지 말 것. `source_file_ref?.file_url` 이 있으면 **원본 문서를 여는 링크**("원본 파일 보기", 새 탭)로 표시. sha256 은 작게 병기(선택).
   - file_url 이 이미지로 보이면(확장자/패턴) **`<img>` 인라인 표시 시도 + onError 시 링크로 graceful fallback**(CORS/권한 실패 대비). 확실치 않으면 링크만으로도 충분.
   - `source_file_ref` 없으면 기존처럼 "원문 참조 없음".
   - ★ 리뷰어는 이 원본 파일을 열어 **codex 플래그의 source_quote(원문 인용)와 대조**한다 — 링크/이미지가 그 용도.
3. (선택·trivial 하면) DialogContent 의 `aria-describedby`/`Description` 경고 해소.

## 제약
- src/ 만, 위 3파일. server·extension·.github 불변. 다른 검토 UI 기능(목록 우선정렬·2-pane·플래그 3열 대조·숫자/의미 확인 게이트·전이 버튼) 회귀 0.

## 검증
- `npm run build` PASS + tsc 0. 기존 테스트 회귀 0.
- 신규 테스트: `ReviewDetailPanel` 에 **객체형 source_file_ref**(`{file_url, sha256}`)를 넘겨도 크래시 없이 렌더되고 file_url 링크가 나오는지 / null 이면 "원문 참조 없음".
- ★ **실렌더 스크린샷 육안 필수**: 상세뷰가 크래시 없이 열리고 좌측에 원본 파일 링크(또는 이미지)가 보이는지(vite/harness + 목업 detail).

## 완료 (★ 순서 B)
- src/ 만. **dev6 금지** — dev2(오딘, 검토 UI 원저자). 커밋 → push → **★ push 확인** → **npm run build PASS 확인** → finish-task foreground 1회 → .done. ANU 독립검증(실렌더)·머지·재배포는 ANU.

## goal_assertions (auto-generated)
- `npm run build`
