Ask: Authenticate GitHub webhook deliveries by their valid HMAC signature so direct deliveries work in production auth modes.
Expected files: src/app/api/pr-followup/webhook/route.ts, src/app/api/pr-followup/webhook/route.test.ts, src/middleware.ts, docs/pr-review-fix-queue.md
Problem: POST /api/pr-followup/webhook runs authorizeRequest(request) before HMAC verification. Real GitHub webhook deliveries carry no Authorization header — GitHub authenticates with x-hub-signature-256 only. So the documented "verify" mode (WEBHOOK_SECRET set, direct GitHub delivery, no gateway) returns 401 Unauthorized at the auth layer before the signature is ever checked. The route only works today when DISPATCH_AUTH_MODE=disabled or behind a gateway that injects header auth (WEBHOOK_GATEWAY_MODE=true). In basic mode the middleware rejects the delivery even earlier. Every signature test in the suite passes Authorization: Bearer …, so the GitHub-shaped request (signature only, no auth header) is never exercised.
Evidence:
src/app/api/pr-followup/webhook/route.ts: const auth = await authorizeRequest(request) runs before verifyWebhookSignature(...)
src/middleware.ts: matcher /((?!api/auth|api/health|...).*) enforces Basic/Bearer on /api/pr-followup/webhook in basic mode
- Reproduction (2026-08-12, vitest harness): POST with
x-github-event: pull_request_review + valid x-hub-signature-256 and no Authorization header → 401 {"error":"Unauthorized"}; same request with Bearer header → processed
src/app/api/pr-followup/webhook/route.test.ts: all signature cases include Authorization: Bearer ${mockToken}; no test covers signature-only delivery
docs/pr-review-fix-queue.md: documents WEBHOOK_SECRET HMAC verification as the primary mode, gateway as the exception
Acceptance:
- A request carrying a valid
x-hub-signature-256 (with WEBHOOK_SECRET set, WEBHOOK_GATEWAY_MODE unset, and no Authorization header) reaches event processing and returns 200 in oidc/legacy/basic auth modes
- A test asserting exactly that GitHub-shaped delivery is added and passes
- Invalid-signature deliveries still 401;
basic-mode middleware no longer blocks the webhook path when signature verification is enabled
Ask: Authenticate GitHub webhook deliveries by their valid HMAC signature so direct deliveries work in production auth modes.
Expected files: src/app/api/pr-followup/webhook/route.ts, src/app/api/pr-followup/webhook/route.test.ts, src/middleware.ts, docs/pr-review-fix-queue.md
Problem:
POST /api/pr-followup/webhookrunsauthorizeRequest(request)before HMAC verification. Real GitHub webhook deliveries carry noAuthorizationheader — GitHub authenticates withx-hub-signature-256only. So the documented "verify" mode (WEBHOOK_SECRETset, direct GitHub delivery, no gateway) returns 401 Unauthorized at the auth layer before the signature is ever checked. The route only works today whenDISPATCH_AUTH_MODE=disabledor behind a gateway that injects header auth (WEBHOOK_GATEWAY_MODE=true). Inbasicmode the middleware rejects the delivery even earlier. Every signature test in the suite passesAuthorization: Bearer …, so the GitHub-shaped request (signature only, no auth header) is never exercised.Evidence:
src/app/api/pr-followup/webhook/route.ts:const auth = await authorizeRequest(request)runs beforeverifyWebhookSignature(...)src/middleware.ts: matcher/((?!api/auth|api/health|...).*)enforces Basic/Bearer on/api/pr-followup/webhookinbasicmodex-github-event: pull_request_review+ validx-hub-signature-256and no Authorization header →401 {"error":"Unauthorized"}; same request with Bearer header → processedsrc/app/api/pr-followup/webhook/route.test.ts: all signature cases includeAuthorization: Bearer ${mockToken}; no test covers signature-only deliverydocs/pr-review-fix-queue.md: documentsWEBHOOK_SECRETHMAC verification as the primary mode, gateway as the exceptionAcceptance:
x-hub-signature-256(withWEBHOOK_SECRETset,WEBHOOK_GATEWAY_MODEunset, and noAuthorizationheader) reaches event processing and returns 200 in oidc/legacy/basic auth modesbasic-mode middleware no longer blocks the webhook path when signature verification is enabled