{
  "pass": false,
  "risks": [
    {
      "severity": "critical",
      "description": "/home/jay/projects/InsuRo/supabase/functions/suggest-topics/index.ts에 Authorization 헤더 확인, JWT 검증, user_subscriptions 플랜 조회가 전혀 없어 토큰 없이 직접 POST해도 AI 호출까지 진행됩니다. 완료 시그니처의 401/403 조건을 충족하지 못합니다."
    },
    {
      "severity": "high",
      "description": "프론트 /home/jay/projects/InsuRo/src/pages/Generate.tsx의 useFeatureGate는 UI 제한일 뿐이며, 서버 함수가 이를 재검증하지 않아 Free 플랜 사용자가 Edge Function URL을 직접 호출해 ai_topic_suggest 기능을 우회할 수 있습니다."
    },
    {
      "severity": "medium",
      "description": "FastAPI /home/jay/projects/InsuRo/server/main.py에는 verify_jwt/require_feature 패턴이 있지만 Generate.tsx는 Supabase Edge Function suggest-topics를 호출하므로 main.py를 수정해도 실제 취약 엔드포인트가 보호되지 않을 수 있습니다."
    },
    {
      "severity": "medium",
      "description": "suggest-topics 함수가 모든 예외를 500으로 반환하므로 인증 실패와 플랜 거부를 추가하더라도 명시적으로 401/403을 먼저 반환하지 않으면 검증 시나리오와 클라이언트 오류 처리 기준이 흐려질 수 있습니다."
    }
  ],
  "suggestions": [
    "suggest-topics Edge Function 시작부에서 Authorization: Bearer 토큰을 필수로 검사하고, Supabase auth.getClaims 또는 getUser로 만료/위조 토큰을 검증하세요.",
    "검증된 sub를 기준으로 user_subscriptions 및 필요 시 organization_subscriptions와 subscription_plans를 조회해 ai_topic_suggest가 허용된 Pro 이상 플랜인지 서버에서 판정하세요.",
    "토큰 없음/무효는 401, 플랜 미달은 403으로 AI 호출 전에 즉시 반환하도록 분기하세요.",
    "Generate.tsx의 suggest-topics 호출 전에 세션 access_token 존재를 확인하고, 가능하면 invoke 옵션 headers에 Authorization을 명시해 동작을 테스트 가능하게 만드세요.",
    "JWT 없음, Free JWT, Pro JWT 케이스를 함수 단위 또는 curl 기반 검증으로 추가하세요."
  ],
  "source": "codex_companion",
  "fallback_reason": null,
  "error": null,
  "task_id": "task-2103",
  "timestamp": "2026-04-22T06:54:28.242169+00:00"
}