name: toss-iap-edge-recovery description: TaillogToss IAP 장애 복구 스킬 — verify-iap-order 401/403 분리 진단, 안전한 권한 처리, toss_orders 영속 복구(v12 기준).
Toss IAP Edge Recovery
verify-iap-order가 실패할 때, 2026-02-28 실기기에서 성공했던 복구 순서를 빠르게 재현한다.
언제 사용하나
- 구매 완료가 떠도
verify-iap-order가401 invalid jwt또는403 forbidden으로 실패 GET /api/v1/subscription는200인데 결제 지급이 실패public.toss_orders가 증가하지 않음
성공 기준
- Edge 로그:
verify-iap-order최신 버전POST 200 - DB:
public.toss_ordersorder_count증가, 최신 row의toss_status=PAYMENT_COMPLETED,grant_status=granted
표준 복구 순서 (Proven)
- Preflight
list_edge_functions로verify-iap-order의version,verify_jwt,status확인get_logs(service=\"edge-function\")로login-with-toss와verify-iap-order상태코드 페어 확인execute_sql로toss_orders집계 확인
- 401/403 원인 분리
401: 토큰 자체 문제 가능성 우선 확인403: 권한 클레임 불일치 가능성 우선 확인get_logs(service=\"auth\")에서 같은 시각/auth/v1/user상태를 매칭
- 권한 처리 복구 원칙
raw_user_meta_data기반 권한 판정 금지- JWT 검증(
/auth/v1/user) 통과 후:- 앱 역할(
user/trainer/org_owner/org_staff/service_role) 우선 - 없으면
authenticated세션 허용
- 앱 역할(
authenticated에서orgId/trainerUserId요청은403유지
- 데이터 무결성 원칙
- 요청 body
userId신뢰 금지 - 저장
user_id는 항상 검증된 JWT 사용자 id 사용
- 영속화 복구 (v12 패턴)
toss_ordersREST upsert 추가:- endpoint:
/rest/v1/toss_orders?on_conflict=idempotency_key&select=... - headers:
apikey,Authorization: Bearer <user_jwt>,Prefer: resolution=merge-duplicates,return=representation
- endpoint:
idempotency_key기준 멱등 보장- 응답은 DB upsert 결과 row 기준으로 반환
- 배포/검증
deploy_edge_function(name=\"verify-iap-order\", verify_jwt=false)배포- 실기기 로그인 + 구매 1회 수행 후:
- Edge 로그에서 최신
verify-iap-order버전의POST 200확인 toss_orders최신 1~5건 조회로 저장 확인
- Edge 로그에서 최신
검증 SQL
select count(*)::int as order_count, max(created_at) as last_created_at
from public.toss_orders;
select id, user_id, product_id, idempotency_key, toss_status, grant_status, amount, toss_order_id, created_at
from public.toss_orders
order by created_at desc
limit 5;
주의사항
verify_jwt=false를 쓸 때는 함수 내부/auth/v1/user검증이 반드시 있어야 한다.authenticated허용은 B2C 결제 복구용이며, 조직/트레이너 지급 컨텍스트는 별도 권한 검증 없이는 열지 않는다.- 문서 상태는
CLAUDE.md에 장문 누적하지 말고docs/PROJECT-STATUS.md에 증적 중심으로 기록한다.