import hashlib import hmac import json from datetime import datetime from uuid import uuid4 from fastapi import APIRouter, HTTPException, Request router = APIRouter(prefix="/api") WEBHOOK_SECRET = "guardia-webhook-secret-2026" def _verify(signature: str, body: bytes) -> bool: expected = "sha256=" + hmac.new( WEBHOOK_SECRET.encode(), body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, signature) def _new_sr() -> str: return f"SR-{datetime.now().strftime('%Y%m%d')}-{str(uuid4())[:6].upper()}" @router.post("/messenger/webhook") async def receive_webhook(request: Request): body = await request.body() sig = request.headers.get("X-Messenger-Signature", "") # 개발 환경에서 서명 검증 생략 (프로덕션에서 활성화) # if sig and not _verify(sig, body): # raise HTTPException(status_code=403, detail="Invalid signature") payload = json.loads(body) if payload.get("bot") or not payload.get("text", "").strip(): return {"status": "IGNORED"} sr_id = _new_sr() return {"status": "ACCEPTED", "sr_id": sr_id} @router.post("/sr/approve/{sr_id}") async def approve_sr(sr_id: str): return {"status": "APPROVED", "sr_id": sr_id, "message": f"SR {sr_id} 승인 완료 — 실행을 시작합니다."} @router.post("/sr/reject/{sr_id}") async def reject_sr(sr_id: str): return {"status": "REJECTED", "sr_id": sr_id, "message": f"SR {sr_id} 반려 처리되었습니다."} @router.post("/killswitch/confirm") async def killswitch_confirm(): return {"status": "STOPPED", "message": "모든 진행 중인 작업이 중단되었습니다."} @router.post("/killswitch/cancel") async def killswitch_cancel(): return {"status": "CANCELLED", "message": "Kill-Switch 취소되었습니다."}