diff --git a/RELEASE_NOTES_v2.2.43.md b/RELEASE_NOTES_v2.2.43.md new file mode 100644 index 0000000..a3cc95e --- /dev/null +++ b/RELEASE_NOTES_v2.2.43.md @@ -0,0 +1,16 @@ +# Release Notes v2.2.43 + +Dato: 3. marts 2026 + +## Fix: Synlige Mission webhook logs +- Tilføjet eksplicit logging for Mission telefoni-webhooks (`ringing`, `answered`, `hangup`) med call-id, nummer, kø og HTTP-metode. +- Tilføjet warning logs ved manglende/ugyldig Mission webhook token. +- Gør det nemt at fejlsøge Yealink callbacks i `podman logs`. + +## Ændrede filer +- `app/dashboard/backend/mission_router.py` +- `VERSION` + +## Drift +- Deploy med: `./updateto.sh v2.2.43` +- Se webhook-log events med: `podman logs -f bmc-hub-api-v2 | grep -E "Mission webhook|forbidden|token"` diff --git a/VERSION b/VERSION index 4543a20..e3a4d65 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.42 +2.2.43 diff --git a/app/dashboard/backend/mission_router.py b/app/dashboard/backend/mission_router.py index fe73725..37b4fac 100644 --- a/app/dashboard/backend/mission_router.py +++ b/app/dashboard/backend/mission_router.py @@ -72,10 +72,12 @@ def _get_webhook_token() -> str: def _validate_mission_webhook_token(request: Request, token: Optional[str] = None) -> None: configured = _get_webhook_token() if not configured: + logger.warning("Mission webhook token not configured for path=%s", request.url.path) raise HTTPException(status_code=403, detail="Mission webhook token not configured") candidate = token or request.headers.get("x-mission-token") or request.query_params.get("token") if not candidate or candidate.strip() != configured: + logger.warning("Mission webhook forbidden for path=%s", request.url.path) raise HTTPException(status_code=403, detail="Forbidden") @@ -140,6 +142,14 @@ async def mission_ws(websocket: WebSocket): async def mission_telefoni_ringing(event: MissionCallEvent, request: Request, token: Optional[str] = Query(None)): _validate_mission_webhook_token(request, token) + logger.info( + "☎️ Mission webhook ringing call_id=%s caller=%s queue=%s method=%s", + event.call_id, + event.caller_number, + event.queue_name, + request.method, + ) + timestamp = event.timestamp or datetime.utcnow() context = MissionService.resolve_contact_context(event.caller_number) queue_name = (event.queue_name or "Ukendt kø").strip() @@ -216,6 +226,14 @@ async def mission_telefoni_ringing_get(request: Request, token: Optional[str] = async def mission_telefoni_answered(event: MissionCallEvent, request: Request, token: Optional[str] = Query(None)): _validate_mission_webhook_token(request, token) + logger.info( + "✅ Mission webhook answered call_id=%s caller=%s queue=%s method=%s", + event.call_id, + event.caller_number, + event.queue_name, + request.method, + ) + execute_query( """ UPDATE mission_call_state @@ -251,6 +269,14 @@ async def mission_telefoni_answered_get(request: Request, token: Optional[str] = async def mission_telefoni_hangup(event: MissionCallEvent, request: Request, token: Optional[str] = Query(None)): _validate_mission_webhook_token(request, token) + logger.info( + "📴 Mission webhook hangup call_id=%s caller=%s queue=%s method=%s", + event.call_id, + event.caller_number, + event.queue_name, + request.method, + ) + execute_query( """ UPDATE mission_call_state