Gitea's X-Gitea-Signature header contains raw hex HMAC-SHA256.
GitHub's X-Hub-Signature-256 uses the sha256= prefix.
verifySignature now normalises both formats to raw hex before
timingSafeEqual comparison, so pushes from Gitea trigger deploys.
- webhook.js: fail-closed on missing WEBHOOK_SECRET (exits at startup,
never accepts unsigned requests)
- webhook.js: single-slot queue — push during deploy is held and runs
after current deploy completes (not silently dropped)
- deploy.sh + health-check.sh: URL corrected to /api/healthz