# InsuRo 소식지 검토 상세뷰 크래시 수정 (task-2907, #186, 260806) — 머지·배포 완료

- 작업: task-2907 / dev2(오딘)·프레이야(프론트 sonnet) / Lv.1 hotfix
- 증상: 관리자 소식지 검토 상세뷰 항목 클릭 시 **React #31 크래시** ("Objects are not valid as a React child, object with keys {sha256, file_url}"). 회장 실클릭 재현.
- 근본원인: 백엔드 `source_file_ref`는 jsonb **객체** `{file_url, sha256}`(migration 017 / `newsletter_review.py:354` `dict`)인데, 프론트 `reviewApi.ts`가 `string | null`로 오인 → `ReviewDetailPanel.tsx`가 좌측 pane에서 `{detail.source_file_ref}`로 **객체를 직접 렌더** → 크래시.
- 수정(src/ 3파일, additive/버그픽스):
  - `reviewApi.ts`: `SourceFileRef {file_url?, sha256?}` 타입 추가, `source_file_ref: SourceFileRef | null`.
  - `ReviewDetailPanel.tsx`: 객체 직접 렌더 제거 → `file_url` 링크(새 탭 noopener), 이미지 확장자면 `<img>` 인라인+onError graceful fallback(`imgFailed` state), sha256 병기, file_url 없으면 "원문 참조 없음". (데이터가 `file_url` 없이 `{path:...}`로 와도 크래시 없이 "원문 참조 없음" — robust)
  - `ReviewDetailPanel.test.tsx`: mock 객체형 교체 + 신규 3 테스트.

## ANU 독립검증 (순서 B)
- 근본원인 실재 확인: base(main 2ea5096)에 버그 실재(`{detail.source_file_ref||...}`), 백엔드 jsonb dict 계약 확인.
- vitest 7/7 PASS(재현). tsc: 신규 타입에러 **0**(branch 6 = base 6 동일 pre-existing: CommunityBoard/HistoryGroupCard/use-user-tokens×2/AdminSubscriptions/sw-bypass).
- PR CI 전 게이트 PASS(ci·diagnostic·**e2e-test**·guard·qc-check·merge-safety·lock-in·gemini-review-gate 등) → mergeStateStatus CLEAN. e2e도 통과=회귀 0.

## 머지·배포
- PR **#186** squash → `8c26989` (origin/main). base=2ea5096.
- CF Pages 배포: `wrangler pages deploy dist --project-name insuro --branch main` → https://76b5c76c.insuro.pages.dev. **insuro.biz HTTP 200** 확인(2026-08-06 10:37 KST).
- 마이그레이션/백엔드/익스텐션 무관 → 회장 추가 rollout 불필요.

## 회장 후속(선택)
- 관리자 검토 화면에서 상세뷰 실클릭 육안 재확인(크래시 부재).
