{
  "task_id": "task-2119",
  "result": "PASS",
  "auditor": "loki",
  "timestamp": "2026-04-23T04:12:33Z",
  "findings": [
    {
      "id": "F-01",
      "severity": "HIGH",
      "category": "접근 제어 우회",
      "title": "프론트엔드 단독 차단 — 서버 직접 호출 우회 가능",
      "detail": "FeatureGate.tsx / use-feature-access.ts는 UI 렌더링 차단 역할만 수행한다. server/main.py require_feature가 JWT 검증 + 플랜 확인 + DB features 확인을 모두 수행하므로, 서버 엔드포인트가 require_feature를 통해 보호되는 한 프론트 우회는 실질적 위협이 아니다. 단, require_feature를 사용하지 않는 엔드포인트가 존재할 경우 우회 가능 — 엔드포인트별 데코레이터 적용 여부 검토 권고.",
      "status": "CONDITIONAL_PASS",
      "recommendation": "모든 민감 엔드포인트에 require_feature 데코레이터 적용 여부를 정기적으로 감사할 것"
    },
    {
      "id": "F-02",
      "severity": "MEDIUM",
      "category": "fail-open 정책",
      "title": "feature key 부재 시 통과 (fail-open) — 신규 기능 보호 누락 가능성",
      "detail": "FeatureGate.tsx 및 use-feature-gate.ts 모두 dbGate.value === null (DB에 키 없음) 시 접근 허용. 서버 측도 features dict에 key 없으면 차단하지 않음. 신규 기능 출시 시 DB features에 키를 누락하면 모든 플랜 사용자에게 노출된다.",
      "status": "RISK_ACCEPTED",
      "recommendation": "신규 feature_key 추가 시 DB subscription_plans.features 업데이트를 배포 체크리스트에 필수 항목으로 포함. 또는 PLAN_FEATURE_MAP에 없는 키를 require_feature가 ValueError로 거부하는 현재 동작을 기본값으로 유지."
    },
    {
      "id": "F-03",
      "severity": "LOW",
      "category": "인젝션/조작",
      "title": "feature_key 값 조작 가능성",
      "detail": "feature_key는 클라이언트가 직접 전달하지 않고 서버 코드(PLAN_FEATURE_MAP)에서 조회한다. require_feature에서 Unknown feature_key 시 ValueError를 raise하여 등록되지 않은 키는 거부됨. 프론트엔드의 planFeatureMap도 빌드 타임 상수. SQL 인젝션 경로 없음 (ORM/Supabase client 사용). 조작 위험 없음.",
      "status": "PASS",
      "recommendation": "없음"
    },
    {
      "id": "F-04",
      "severity": "LOW",
      "category": "캐시 보안",
      "title": "React useEffect 단발성 fetch — 세션 중 DB 변경 즉시 반영 안 됨",
      "detail": "use-feature-gate.ts의 useEffect는 컴포넌트 마운트 시 1회만 실행 (의존성: featureKey). 관리자가 DB에서 features를 OFF로 변경해도 현재 세션 사용자는 페이지 새로고침 전까지 최대 세션 유지 시간 동안 프론트 UI에서 기능이 활성화된 것처럼 보일 수 있다. 단, 실제 API 호출은 서버의 require_feature가 매 요청마다 DB를 조회하여 차단하므로 실질적 보안 우회는 발생하지 않음.",
      "status": "PASS",
      "recommendation": "필요시 관리자 긴급 차단 시나리오에서 서버 측 즉시 차단만으로 충분함을 팀에 공유. UI 불일치가 UX 문제가 된다면 polling 또는 Supabase realtime 구독 검토 가능."
    }
  ],
  "summary": "접근 제어 변경 보안 감사 통과. 서버 require_feature가 JWT 검증, 플랜 확인, DB features 확인을 모두 수행하여 실질적 우회 경로 없음. fail-open 정책(F-02)은 신규 기능 배포 프로세스 준수를 전제로 위험 수용. 캐시(세션 내 단발성 fetch)는 서버 측 매 요청 검증으로 보완되어 보안 우회 없음. 고위험 발견사항 없음, 권고사항 2건(F-01, F-02) 기록."
}