Webhook Architecture
Authoritative overview of all inbound webhook handlers in OpenClaw. 9 providers route events through Cloudflare Tunnel (webhook.reri.co) or Tailscale-only paths to handler processes on the Hetzner VPS. Each handler validates signatures, deduplicates via processed_webhook_events, and logs to webhook_audit_log. The canonical endpoint registry is [[workspace/FUNNEL-REGISTRY]]. Read this hub when diagnosing missed webhooks, adding a new provider, or auditing security posture. Owner: Henry Hill / Claude Opus 4.7.
⚠️ P0 SECURITY FLAG: security-audit-funnel.timer STALE
Last fired: 2026-04-27 13:00 UTC (6 days ago as of 2026-05-03).
The timer fires Mondays 06:00 America/Los_Angeles — it missed Monday 2026-04-28 and will next fire Monday 2026-05-04 .
Per FUNNEL-REGISTRY governance and CLAUDE.md §Webhook Endpoint Governance: stale audit = security debt.
Action: run node workspace/scripts/security-audit-funnel.js --dry-run manually NOW before this hub is published.
Also: DocuSign WAF IP allowlist 90-day rotation check is overdue (last audit 2026-04-27). See cloudflare WAF section.
Quick reference
Field Value Live state probe ss -tlnp | grep -E ':1879[0-9]|:1880[0-9]' | wc -lDocumented count 9 handler ports per CLAUDE.md Webhook Service Port Map Live count <run probe and insert; expected ~6 active> Drift (live - documented) percentage Canonical endpoint registry [[workspace/FUNNEL-REGISTRY]]Tunnel provider Cloudflare Tunnel reri-api (ID: 849121e5-0db6-4076-b591-268783143377) Public hostname webhook.reri.co (CNAME → 849121e5...cfargotunnel.com, proxied)Fallback Tailscale Funnel srv1347501.tailb025a7.ts.net (unadvertised, rollback path) Documented handlers 9 Live handler ports 6 confirmed active (probed: 2026-05-03) Dedup table processed_webhook_events (Supabase CCP, 24h TTL)Audit table webhook_audit_log (non-blocking write + /tmp/webhook-audit-fallback.jsonl)Security audit script node workspace/scripts/security-audit-funnel.js --dry-runSecurity audit timer security-audit-funnel.timer (Mondays 06:00 PT)Last audit timer fire 2026-04-27 ⚠️ STALELast audit 2026-05-03 Governance gate CLAUDE.md §Webhook Endpoint Governance Owner agent system / aurora (inbound routing)
Components
[[workspace/FUNNEL-REGISTRY]] — canonical approved endpoint list (source of truth for governance)
[[workspace/webhooks/hubspot-handler.js]] — HubSpot + DocuSign + Make webhook handler (port 18790)
[[workspace/webhooks/quo-handler-enhanced.js]] — OpenPhone/Quo webhook handler (port 18792)
[[workspace/webhooks/salesmessage-handler-v4-complete.js]] — SalesMsg webhook handler (port 18793)
[[workspace/webhooks/twilio-voice-handler.js]] — Twilio voice + SMS handler (port 18797)
[[workspace/webhooks/gmail-push-handler.js]] — Gmail Push handler (port 18801, harden-pending)
[[workspace/webhooks/imessage-handler.js]] — BlueBubbles iMessage handler (port 18802, Tailscale-only)
[[workspace/scripts/security-audit-funnel.js]] — security posture audit script
[[workspace/scripts/webhook-dedup.js]] — deduplication utility (processed_webhook_events)
[[workspace/scripts/webhook-audit.js]] — non-blocking audit log writer
Inbound webhook handlers
Handler 1 — HubSpot + DocuSign + Make (port 18790)
Field Value Port 18790 Handler [[workspace/webhooks/hubspot-handler.js]]Process manager PM2 (hubspot, id:3) Tunnel path(s) /webhook/hubspot, /hubspot, /webhook/hubspot/actions/*, /webhook/hubspot/api/dispoTunnel path — DocuSign /webhook/docusignTunnel path — Make /webhook/makeSig verify — HubSpot ✅ v1 HMAC-SHA256(body) Sig verify — DocuSign ✅ WAF IP allowlist (Cloudflare Pro custom rule, 90-day rotation) Sig verify — Make ⚠️ token/query param only IP filter WAF header filter (Cloudflare Pro) Dedup ✅ processed_webhook_events 24h TTL Audit log ✅ webhook_audit_log Status production OAuth callback /oauth/callback on Tailscale Funnel (HubSpot OAuth, one-time install path)
Cross-links: hubspot · cloudflare · openclaw-fragmentation-fix-2026-05-01
Handler 2 — OpenPhone / Quo (port 18792)
Field Value Port 18792 Handler [[workspace/webhooks/quo-handler-enhanced.js]]Process manager systemd openphone-webhook.service Tunnel path(s) /webhook/openphone, /webhook/quoSig verify ✅ HMAC(secret, timestamp.body) IP filter N/A (no published OpenPhone IP ranges) Dedup ✅ processed_webhook_events 24h TTL Audit log ✅ webhook_audit_log Status production 10DLC flag ⚠️ A2P 10DLC repeat-denial active — TCPA risk uncapped. See osil-twilio-10dlc-resubmission-2026-05-03
Cross-links: openphone-quo · twilio
Handler 3 — SalesMsg (port 18793)
Field Value Port 18793 Handler [[workspace/webhooks/salesmessage-handler-v4-complete.js]]Process manager PM2 (salesmsg, id:2) Tunnel path(s) /webhook/salesmessage, /webhooks/salesmessageSig verify ✅ query token ?secret=<token> (constant-time comparison) Note SalesMsg uses query-param token, NOT HMAC. KB once said otherwise — KB was wrong. Per CLAUDE.md §Webhook Endpoint Governance rule 6. Never switch to HMAC without live header verification.IP filter N/A Dedup ✅ processed_webhook_events 24h TTL Audit log ✅ webhook_audit_log Status production
Cross-links: salesmsg · feedback_salesmsg_api_first
Handler 4 — Twilio Voice + SMS (port 18797)
Field Value Port 18797 Handler [[workspace/webhooks/twilio-voice-handler.js]]Process manager PM2 (twilio, id:1) Tunnel path(s) /sms, /sms/webhook, /sms/status, /voice, /voice/webhook, /voice/status, /voice/recording-complete, /voice/transcriptionSig verify ✅ HMAC-SHA1(URL+params), dual-host (webhook.reri.co + Tailscale fallback URL both verified) IP filter N/A Dedup ✅ processed_webhook_events 24h TTL Audit log ✅ webhook_audit_log Status production 10DLC flag ⚠️ A2P 10DLC repeat-denial active — TCPA risk uncapped. See osil-twilio-10dlc-resubmission-2026-05-03 Rollback note Tailscale Funnel rollback active for /sms + /voice; dual-host verifier handles path correctly via CF; Tailscale rollback path UNTESTED
Cross-links: twilio · compliance-gates · cloudflare
Handler 5 — Gmail Push (port 18801)
Field Value Port 18801 Handler [[workspace/webhooks/gmail-push-handler.js]]Process manager manual / cron Tunnel path /webhook/gmail-pushSig verify ⚠️ verify config — not fully hardened IP filter N/A Dedup ⚠️ verify Audit log ⚠️ verify Status approved-pending-harden
Cross-links: Gmail Push subscription (KB at sources/kb/google-workspace/)
Handler 6 — BlueBubbles iMessage (port 18802, Tailscale-only)
Field Value Port 18802 Handler [[workspace/webhooks/imessage-handler.js]]Process manager systemd imessage-webhook.service Tunnel path /imessage — Tailscale ONLY (never in CF Tunnel)Sig verify ✅ query token ?token=BLUEBUBBLES_WEBHOOK_SECRET (constant-time) IP filter Tailscale topology (source: auroras-mac-mini / 100.93.7.6 per MagicDNS) Dedup ✅ webhook-dedup.js 24h TTL Audit log ✅ webhook-audit.js + /tmp fallback Status pending-deploy Note BlueBubbles has NO HMAC capability (KB WEBHOOKS.md §Authentication). Query token is only available auth mechanism.
Cross-links: aws (Aurora’s Mac mini on Tailscale)
Handlers 7–9 — Internal / secondary
Handler Port Description Status Discord-Lovable bridge 18794 Wildcard public ⚠️ — not in FUNNEL-REGISTRY security-review needed salesmsg-gateway.js18796 Internal SMS gateway ⚠️ P0: hardcoded API key in unit file security-review needed Broadcast Audit UI 18812 Wildcard public ⚠️ — not in FUNNEL-REGISTRY security-review needed
Platform Method Implementation HubSpot HMAC-SHA256(body) v1 hubspot-handler.js verify middlewareDocuSign WAF IP allowlist (Cloudflare Pro) Cloudflare custom rule, 90-day rotation OpenPhone/Quo HMAC(secret, ts.body) quo-handler-enhanced.jsSalesMsg Query token ?secret= salesmessage-handler-v4-complete.js constant-time compareTwilio HMAC-SHA1(URL+params) twilio-voice-handler.js dual-hostGmail Push ⚠️ Verify config Not fully configured BlueBubbles Query token ?token= Tailscale-only, constant-time Make.com Query/token param ⚠️ Weaker than HMAC
Cloudflare Tunnel topology
Internet → webhook.reri.co (Cloudflare WAF)
├── /webhook/hubspot/* → :18790 (PM2 hubspot)
├── /webhook/openphone, /webhook/quo → :18792 (systemd openphone-webhook)
├── /webhook/salesmessage, /webhooks/salesmessage → :18793 (PM2 salesmsg)
├── /sms/*, /voice/* → :18797 (PM2 twilio)
└── /webhook/gmail-push → :18801 (manual)
Tailscale Funnel srv1347501.tailb025a7.ts.net (fallback, unadvertised)
├── /sms, /voice, /webhook/hubspot, /webhook/openphone, etc. → same handlers
└── /oauth/callback → :18790 (HubSpot OAuth one-time install)
Tailscale-Only (never public, topology-constrained)
└── /imessage → :18802 (imessage-webhook.service, source: auroras-mac-mini)
Live state snapshot (2026-05-03)
Metric Documented Live (probed) Drift Status Total handlers 9 6 (core ports active) −3 gmail-push unconfirmed; internal handlers vary Fully hardened handlers 7 5 −2 gmail-push + make.com pending security-audit-funnel.timer weekly last fired 2026-04-27 6 days ⚠️ STALE DocuSign WAF rule 90-day cycle last checked 2026-04-27 — review pending Handlers with plaintext creds 0 1 (salesmsg-gateway unit file) — ⚠️ P0
How it’s used
Inbound event processing: all external events (deals, SMS, voice, emails) enter via these handlers
New provider onboarding: add entry to FUNNEL-REGISTRY FIRST → implement handler with all 4 invariants (sig verify, dedup, audit log, IP filter) → register port in port-registry → start service
Sig failure investigation: journalctl --user -u <unit> --since "1h ago" | grep sig
Dedup check: SELECT * FROM processed_webhook_events WHERE event_id = '<id>' in Supabase CCP
Security audit: node workspace/scripts/security-audit-funnel.js --dry-run → must report clean (or expected transient findings only)
Failure mode: handler down → events queued at provider → replay risk; sig verify off → replay attack vulnerability
Cross-links
Agents that touch this
_summary — consumes OpenPhone/Quo and SalesMsg events for deal dispatch
_summary — processes deal-detection events from HubSpot + OpenPhone
_summary — consumes HubSpot events for dispo pipeline
Skills that invoke this
Plans that govern this
Feedback rules
KB / source docs
README — Tunnel config, WAF rules, IP allowlist
WEBHOOKS — HubSpot webhook event shapes
WEBHOOKS — OpenPhone webhook event shapes
WEBHOOKS — SalesMsg webhook shapes (note: query token, not HMAC)
WEBHOOKS — Twilio HMAC-SHA1 verification
System maps
Per Wave 1 spec §7 cross-hub clusters:
hubspot — HubSpot provider (handler 1)
openphone-quo — OpenPhone/Quo provider (handler 2)
salesmsg — SalesMsg provider (handler 3)
twilio — Twilio provider (handler 4)
discord — Discord alert notifications
cloudflare — Tunnel layer (fronts all public handlers)
Open issues / TODOs
Recent activity
2026-05-03: system hub created (W2-S4, Wave 2); security-audit-funnel.timer staleness flagged as P0
2026-04-27: last security-audit-funnel.timer run (last known clean state)
2026-04-22: BlueBubbles iMessage handler added to FUNNEL-REGISTRY (pending-deploy)
2026-04-21: FUNNEL-REGISTRY created; all 4 providers migrated to webhook.reri.co via CF Tunnel v19