Plugin webhooks
SCM + tracker plugins optionally participate in Coro’s webhook story so hybrid tenants can resume parked jobs without relying solely on polling.
Manifest descriptor
webhook?: { pathSuffix?: string algorithm: 'hmac-sha256' | 'hmac-sha1' | 'none' header: string // e.g. X-Hub-Signature-256 format: 'sha256=<hex>' | 'sha1=<hex>' | '<hex>' | '<plain>'}The cloud control plane stores per-team rows describing the same tuple; when Bitbucket/GitHub POSTs to https://cloud/webhook/:teamId/:pluginId, the edge:
- Loads the secret + algorithm.
- Recomputes HMAC using
rawBody. - Compares against the header respecting
format. - Forwards
{ pluginId, headers, rawBodyBase64 }acrossWS /ws/runner.
normalizeInbound
Once the payload reaches the owning runner, makePluginWebhookNormalizer dispatches to plugin.normalizeInbound which must:
- Decode provider JSON/XML.
- Populate an
ExternalRefviabuildExternalRef({ kind, pluginId, externalId, repoKey?, url? }). - Return
nullif the event should be ignored.
buildExternalRef enforces invariants (e.g., pull_request must carry repoKey).
HMAC helpers
@coro-ai/plugin-sdk exposes verifyHmacSignature mirroring cloud behaviour so plugins can double-check signatures in local dev or custom HTTP routes.
Legacy routes
Some releases still accept /webhook/:provider/:teamId aliases, but operators should configure providers against the generic /webhook/:teamId/:pluginId path documented in packages/runner/src/cloud/routes/webhooks.ts.