{
  "pass": false,
  "risks": [
    {
      "severity": "critical",
      "description": "프론트엔드는 FastAPI /api/insuro/ai/generate가 아니라 Supabase Edge Function ${SUPABASE_FUNCTION_BASE}/generate-content를 호출합니다(src/pages/Generate.tsx:141-148, src/config/api.ts:8). 설계 문서의 조사 방향이 server/main.py 중심이라 실제 실패 지점을 놓칠 위험이 큽니다."
    },
    {
      "severity": "critical",
      "description": "Authorization 헤더에 사용자 세션 access_token이 아니라 VITE_SUPABASE_PUBLISHABLE_KEY를 Bearer로 보내고 있습니다(src/pages/Generate.tsx:147). Edge Function은 이 토큰에서 userId를 추출하지 못하면 플랜, 채널, 토큰 제한 검증을 건너뜁니다(supabase/functions/generate-content/index.ts:310-343). 기능 실패와 보안 우회가 동시에 발생할 수 있습니다."
    },
    {
      "severity": "high",
      "description": "Edge Function은 channel 검증에 settings.channel 또는 contentType을 사용하지만, 프론트는 contentType으로 '네이버 블로그' 같은 label을 보냅니다(src/pages/Generate.tsx:151, src/data/generateOptions.ts:6-8). DB allowed_channels가 blog/naver-blog 같은 value 기반이면 정상 사용자가 403을 받을 수 있습니다."
    },
    {
      "severity": "high",
      "description": "환경 변수 확인 범위가 부족합니다. .env에는 GOOGLE_AI_API_KEY, SUPABASE_SERVICE_ROLE_KEY, SUPABASE_ANON_KEY가 보이지 않는데 Edge Function은 런타임에서 이 값들을 직접 요구합니다(supabase/functions/generate-content/index.ts:285-299, 316). Vite 빌드 성공만으로 배포된 Supabase Function의 비밀값 누락을 잡을 수 없습니다."
    },
    {
      "severity": "medium",
      "description": "프론트의 403 처리 메시지가 모든 403을 '채널 업그레이드'로 고정합니다(src/pages/Generate.tsx:161-166). 모델 권한, 토큰/플랜 문제, 채널 매핑 오류가 모두 같은 안내로 보일 수 있어 원인 파악이 어려워집니다."
    },
    {
      "severity": "medium",
      "description": "FastAPI generate 엔드포인트는 prompt/system_prompt/model_tier 스키마를 기대하지만(server/main.py:605-610), 프론트 요청은 topic/contentType/channelPrompt/settings 스키마입니다. 향후 FastAPI로 우회 수정할 경우 어댑터 없이 연결하면 422 또는 잘못된 프롬프트 생성이 발생합니다."
    }
  ],
  "suggestions": [
    "조사 대상을 Supabase Edge Function generate-content로 명확히 바꾸고, 프론트 → Edge Function → 외부 AI API 경로를 기준으로 로그와 네트워크 탭을 확인하세요.",
    "Generate.tsx에서 supabase.auth.getSession()의 session.access_token을 Authorization Bearer로 보내도록 변경하세요. 익명 허용이 필요 없다면 generate-content의 JWT 검증 정책도 재검토하세요.",
    "contentType은 표시 label이 아니라 channel.value 또는 별도 channel key를 보내고, Edge Function의 allowed_channels 값 체계와 통일하세요.",
    "검증 시나리오에 npm run build 외에 supabase functions serve/deployed function 호출 테스트, OPTIONS preflight, 실제 POST 응답 상태/본문 확인을 추가하세요.",
    "Edge Function 런타임 비밀값(GOOGLE_AI_API_KEY, SUPABASE_SERVICE_ROLE_KEY, SUPABASE_ANON_KEY 또는 Supabase 기본 env 제공 여부)을 배포 환경에서 점검하도록 문서에 추가하세요.",
    "프론트 403 처리에서 error 코드(channel_not_allowed, upgrade_required, token_exhausted 등)를 분기해 사용자와 운영자가 실제 원인을 알 수 있게 하세요."
  ],
  "source": "codex_companion",
  "fallback_reason": null,
  "error": null,
  "task_id": "task-2099",
  "timestamp": "2026-04-22T06:21:59.474853+00:00"
}