You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* feat(webhooks): add standalone Telegram + HelloSign inbound providers
Both providers had verifier logic at the connector-adapter level but no
standalone WebhookProvider, so the inbound webhook router (and consumers that
drive it — e.g. a per-connection inbound route) could not use them. Add them to
webhooks/providers.ts (auto-exported from /webhooks):
- telegramWebhookProvider: Telegram authenticates webhooks by echoing the
secret_token set at setWebhook time in the X-Telegram-Bot-Api-Secret-Token
header (the body is NOT signed), so we constant-time compare it to the
per-connection secret. update_id is the idempotency anchor; the first present
update key names the event (telegram.message, telegram.callback_query, ...).
New capability — the connector only had a setWebhook mutation + a TODO.
- hellosignWebhookProvider: Dropbox Sign has no signature header; the body
carries event.event_hash = HMAC_SHA256(apiKey, event_time + event_type), so
`secret` is the account API key. Handles JSON, form-urlencoded `json=`, and
multipart `name="json"` bodies (mirrors the connector adapter's extraction).
Tests cover verify pass/fail/missing and parse for both (incl. HelloSign's
form-encoded body). Full suite (4077) + typecheck + build green. Additive
exports only: 0.39.0 -> 0.40.0.
* fix(webhooks): harden telegram and hellosign inbound providers
- HelloSign: key providerEventId on a sha256 digest of the parsed body rather than event_hash. event_hash = HMAC(apiKey, event_time + event_type), so two distinct same-type events in the same second collide and the second would be dropped by delivery dedup. The body digest is stable across redeliveries of one event and distinct across events that differ in content.
- Telegram: extend TELEGRAM_UPDATE_KEYS to the full Bot API Update set (business_connection, edited_business_message, deleted_business_messages, message_reaction, message_reaction_count, purchased_paid_media, chat_boost, removed_chat_boost) so those deliveries classify by type instead of telegram.unknown.
- Tests: multipart name="json" verify+parse, same-second collision + redelivery stability, and a message_reaction regression.
typecheck clean; full suite green (4080).
* fix(webhooks): decode form-urlencoded hellosign bodies with URLSearchParams
The `json=` fallback used decodeURIComponent, which does not convert `+` to a space — but application/x-www-form-urlencoded encodes spaces as `+`. Space-bearing fields (e.g. signature_request.title) were corrupted, and JSON with structural whitespace could fail to parse. Switch to URLSearchParams.get('json'), which decodes `+` and percent-escapes correctly. Applied to both the new webhook provider and the HelloSign connector adapter it mirrors.
typecheck clean; full suite green (4081).
* fix(webhooks): make hellosign provider production-correct (ACK body + canonical event id)
- Router: add an optional WebhookProvider.successResponse so a provider can declare the 200 ACK body/headers it needs; WebhookRouter.handle() returns it on a verified delivery instead of the default { received, total } JSON. The frozen status contract is unchanged.
- HelloSign: declare the literal 'Hello API Event Received' ACK (text/plain) Dropbox Sign requires — without it a verified delivery is treated as failed and retried indefinitely.
- HelloSign: prefer the canonical event.event_id for providerEventId, falling back to the body digest only when it is absent (parity with the connector adapter; the digest still avoids the event_hash same-second collision).
- Tests: event_id preference, the ACK field, and a router-level assertion that a verified HelloSign delivery returns 200 with body 'Hello API Event Received'.
typecheck clean; full suite green (4084).
* fix(webhooks): linear multipart json extraction, removing quadratic backtracking
The HelloSign multipart `name="json"` fallback used a regex with two sequential lazy scans (`name="json"[^]*?\r?\n\r?\n([\s\S]*?)\r?\n--`). On a body with many `\r\n\r\n` separators and no closing boundary it backtracks quadratically — measured ~26s for a 400KB body — so a crafted POST to the public webhook ingress could stall the event loop. Replace it with indexOf + fixed-shape separator probes (no `*`/`+` quantifiers), which extract the same part in a single linear pass (~1.5ms at 1MB) with identical semantics. Applied to both the webhook provider and the connector adapter that share the pattern.
typecheck clean; full suite green (4085).
* docs(webhooks): list telegram and hellosign providers in the router table
The package now exports telegramWebhookProvider and hellosignWebhookProvider; add them to the WebhookRouter row of the API reference.
0 commit comments