Skip to content

[OBJ-19] Universal Webhook Ingestion — Event-Driven Trigger Gateway #30

@G9Pedro

Description

@G9Pedro

Summary

Build a universal webhook ingestion layer that lets any external service (GitHub, Linear, Cursor, Slack, PagerDuty, custom) POST events into WorkGraph, which normalizes them and routes to the appropriate trigger → run → evidence flow.

Why This Matters

WorkGraph has the trigger-run-evidence loop (OBJ-07) and will have programmable trigger primitives (OBJ-10), but no way for external systems to actually FIRE those triggers via HTTP. Without this, every integration is bespoke glue code.

Cursor Automations solved this exact problem — they built a generic event gateway with provider adapters. WorkGraph needs the equivalent as the receiving end.

What to Build

1. Webhook Gateway (packages/webhook-gateway/)

  • HTTP server (Hono) that receives POST requests from any source
  • Auth: HMAC signature verification (GitHub), bearer tokens, shared secrets
  • Rate limiting and replay protection (idempotency keys)
  • Event queue for async processing

2. Provider Normalizers

Each provider adapter normalizes raw webhooks into a common WorkGraph event schema:

  • GitHub — PR opened/merged/pushed, issue created/closed, push to branch, CI completed
  • Linear — Issue created/status changed, cycle completed
  • Cursor — Agent finished, PR opened by agent
  • Slack — Message in channel, reaction added
  • Generic webhook — Raw JSON passthrough with jq-style field extraction

3. Event → Trigger Router

  • Match incoming normalized events to registered trigger definitions (OBJ-10)
  • Support pattern matching: "when GitHub PR merged on repo X with label Y → fire trigger Z"
  • Fan-out: one event can fire multiple triggers
  • Dead letter queue for unmatched events

4. Event Schema

interface WorkGraphEvent {
  id: string;
  source: "github" | "linear" | "cursor" | "slack" | "webhook";
  type: string; // e.g. "pr.merged", "issue.created"
  timestamp: string;
  payload: Record<string, unknown>;
  metadata: {
    repo?: string;
    actor?: string;
    url?: string;
  };
  idempotencyKey: string;
}

Dependencies

  • OBJ-07 ✅ (Trigger → Run → Evidence Loop)
  • OBJ-10 (Programmable Trigger Primitives) — defines what triggers exist
  • OBJ-11 (Background Dispatch Adapters) — defines where work goes
  • OBJ-18 (Cursor Automations Bridge) — specific adapter

Definition of Done

  • HTTP webhook endpoint accepts events from GitHub, Linear, Cursor
  • Events normalized to common schema
  • Router matches events to trigger definitions and fires runs
  • HMAC/bearer auth verification works
  • At least GitHub + Linear + generic webhook adapters implemented
  • All tests pass, pnpm test passes

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions