Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
5ca66c3
refactor(webhooks): extract provider-specific logic into handler regi…
waleedlatif1 Apr 6, 2026
925be3d
feat(triggers): add Salesforce webhook triggers (#3982)
waleedlatif1 Apr 6, 2026
c9b45f4
feat(triggers): add HubSpot merge, restore, and generic webhook trigg…
waleedlatif1 Apr 6, 2026
62a7700
feat(integrations): add Sixtyfour AI integration (#3981)
waleedlatif1 Apr 6, 2026
796384a
feat(triggers): add Resend webhook triggers with auto-registration (#…
waleedlatif1 Apr 6, 2026
62ea0f1
feat(triggers): add Gong webhook triggers for call events (#3984)
waleedlatif1 Apr 6, 2026
590f376
feat(triggers): add Intercom webhook triggers (#3990)
waleedlatif1 Apr 6, 2026
7ea0693
feat(triggers): add Greenhouse webhook triggers (#3985)
waleedlatif1 Apr 6, 2026
21e5b5c
feat(triggers): add Notion webhook triggers (#3989)
waleedlatif1 Apr 6, 2026
c18f023
feat(analytics): add Google Tag Manager and Google Analytics for host…
waleedlatif1 Apr 6, 2026
8b1d749
feat(triggers): add Vercel webhook triggers with automatic registrati…
waleedlatif1 Apr 6, 2026
cd5cee3
feat(landing): add PostHog tracking for CTA clicks, demo requests, an…
waleedlatif1 Apr 6, 2026
18a7868
feat(triggers): add Zoom webhook triggers (#3992)
waleedlatif1 Apr 6, 2026
5ea63f1
feat(triggers): add Linear v2 triggers with automatic webhook registr…
waleedlatif1 Apr 6, 2026
7e0794c
fix(signup): show multiple signup errors at once (#3987)
TheodoreSpeaks Apr 6, 2026
58571fe
fix(hitl): fix stream endpoint, pause persistence, and resume page (#…
waleedlatif1 Apr 6, 2026
2164cef
fix(mothership): fix url keeping markdown hash on resource switch (#3…
TheodoreSpeaks Apr 7, 2026
8c8c627
feat(block): Conditionally hide impersonateUser field from block, add…
TheodoreSpeaks Apr 7, 2026
25b4a3f
feat(posthog): Add posthog log for signup failed (#3998)
TheodoreSpeaks Apr 7, 2026
df2c47a
fix(copilot): fix copilot running workflow stuck on 10mb error (#3999)
TheodoreSpeaks Apr 7, 2026
8df3f20
fix(blocks): allow tool expansion in disabled mode, improve child dep…
waleedlatif1 Apr 7, 2026
5eb494d
fix(secrets): secrets/integrations component code cleanup (#4003)
icecrasher321 Apr 7, 2026
606477e
feat(home): add folders to resource menu (#4000)
waleedlatif1 Apr 7, 2026
cc8c9e8
feat(home): add double-enter to send top queued message (#4005)
waleedlatif1 Apr 7, 2026
c52834b
fix(subflows): make edges inside subflows directly clickable (#3969)
waleedlatif1 Apr 7, 2026
609ba61
fix(sockets): joining currently deleted workflow (#4004)
icecrasher321 Apr 7, 2026
89ae738
feat(folders): soft-delete folders and show in Recently Deleted (#4001)
waleedlatif1 Apr 7, 2026
64c6cd9
fix(webhooks): harden audited provider triggers (#3997)
waleedlatif1 Apr 7, 2026
8e11c32
fix(resource-menu): consistent height between 1 result and no results…
waleedlatif1 Apr 7, 2026
1e00a06
fix(home): simplify enter-to-send queued message to single press (#4008)
waleedlatif1 Apr 7, 2026
7793583
fix(secrets): restore unsaved-changes guard for settings tab navigati…
waleedlatif1 Apr 7, 2026
68df732
refactor(triggers): consolidate v2 Linear triggers into same files as…
waleedlatif1 Apr 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
668 changes: 159 additions & 509 deletions .agents/skills/add-trigger/SKILL.md

Large diffs are not rendered by default.

212 changes: 212 additions & 0 deletions .agents/skills/validate-trigger/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
---
name: validate-trigger
description: Audit an existing Sim webhook trigger against the service's webhook API docs and repository conventions, then report and fix issues across trigger definitions, provider handler, output alignment, registration, and security. Use when validating or repairing a trigger under `apps/sim/triggers/{service}/` or `apps/sim/lib/webhooks/providers/{service}.ts`.
---

# Validate Trigger

You are an expert auditor for Sim webhook triggers. Your job is to validate that an existing trigger implementation is correct, complete, secure, and aligned across all layers.

## Your Task

1. Read the service's webhook/API documentation (via WebFetch)
2. Read every trigger file, provider handler, and registry entry
3. Cross-reference against the API docs and Sim conventions
4. Report all issues grouped by severity (critical, warning, suggestion)
5. Fix all issues after reporting them

## Step 1: Gather All Files

Read **every** file for the trigger — do not skip any:

```
apps/sim/triggers/{service}/ # All trigger files, utils.ts, index.ts
apps/sim/lib/webhooks/providers/{service}.ts # Provider handler (if exists)
apps/sim/lib/webhooks/providers/registry.ts # Handler registry
apps/sim/triggers/registry.ts # Trigger registry
apps/sim/blocks/blocks/{service}.ts # Block definition (trigger wiring)
```

Also read for reference:
```
apps/sim/lib/webhooks/providers/types.ts # WebhookProviderHandler interface
apps/sim/lib/webhooks/providers/utils.ts # Shared helpers (createHmacVerifier, etc.)
apps/sim/lib/webhooks/provider-subscription-utils.ts # Subscription helpers
apps/sim/lib/webhooks/processor.ts # Central webhook processor
```

## Step 2: Pull API Documentation

Fetch the service's official webhook documentation. This is the **source of truth** for:
- Webhook event types and payload shapes
- Signature/auth verification method (HMAC algorithm, header names, secret format)
- Challenge/verification handshake requirements
- Webhook subscription API (create/delete endpoints, if applicable)
- Retry behavior and delivery guarantees

## Step 3: Validate Trigger Definitions

### utils.ts
- [ ] `{service}TriggerOptions` lists all trigger IDs accurately
- [ ] `{service}SetupInstructions` provides clear, correct steps for the service
- [ ] `build{Service}ExtraFields` includes relevant filter/config fields with correct `condition`
- [ ] Output builders expose all meaningful fields from the webhook payload
- [ ] Output builders do NOT use `optional: true` or `items` (tool-output-only features)
- [ ] Nested output objects correctly model the payload structure

### Trigger Files
- [ ] Exactly one primary trigger has `includeDropdown: true`
- [ ] All secondary triggers do NOT have `includeDropdown`
- [ ] All triggers use `buildTriggerSubBlocks` helper (not hand-rolled subBlocks)
- [ ] Every trigger's `id` matches the convention `{service}_{event_name}`
- [ ] Every trigger's `provider` matches the service name used in the handler registry
- [ ] `index.ts` barrel exports all triggers

### Trigger ↔ Provider Alignment (CRITICAL)
- [ ] Every trigger ID referenced in `matchEvent` logic exists in `{service}TriggerOptions`
- [ ] Event matching logic in the provider correctly maps trigger IDs to service event types
- [ ] Event matching logic in `is{Service}EventMatch` (if exists) correctly identifies events per the API docs

## Step 4: Validate Provider Handler

### Auth Verification
- [ ] `verifyAuth` correctly validates webhook signatures per the service's documentation
- [ ] HMAC algorithm matches (SHA-1, SHA-256, SHA-512)
- [ ] Signature header name matches the API docs exactly
- [ ] Signature format is handled (raw hex, `sha256=` prefix, base64, etc.)
- [ ] Uses `safeCompare` for timing-safe comparison (no `===`)
- [ ] If `webhookSecret` is required, handler rejects when it's missing (fail-closed)
- [ ] Signature is computed over raw body (not parsed JSON)

### Event Matching
- [ ] `matchEvent` returns `boolean` (not `NextResponse` or other values)
- [ ] Challenge/verification events are excluded from matching (e.g., `endpoint.url_validation`)
- [ ] When `triggerId` is a generic webhook ID, all events pass through
- [ ] When `triggerId` is specific, only matching events pass
- [ ] Event matching logic uses dynamic `await import()` for trigger utils (avoids circular deps)

### formatInput (CRITICAL)
- [ ] Every key in the `formatInput` return matches a key in the trigger `outputs` schema
- [ ] Every key in the trigger `outputs` schema is populated by `formatInput`
- [ ] No extra undeclared keys that users can't discover in the UI
- [ ] No wrapper objects (`webhook: { ... }`, `{service}: { ... }`)
- [ ] Nested output paths exist at the correct depth (e.g., `resource.id` actually has `resource: { id: ... }`)
- [ ] `null` is used for missing optional fields (not empty strings or empty objects)
- [ ] Returns `{ input: { ... } }` — not a bare object

### Idempotency
- [ ] `extractIdempotencyId` returns a stable, unique key per delivery
- [ ] Uses provider-specific delivery IDs when available (e.g., `X-Request-Id`, `Linear-Delivery`, `svix-id`)
- [ ] Falls back to content-based ID (e.g., `${type}:${id}`) when no delivery header exists
- [ ] Does NOT include timestamps in the idempotency key (would break dedup on retries)

### Challenge Handling (if applicable)
- [ ] `handleChallenge` correctly implements the service's URL verification handshake
- [ ] Returns the expected response format per the API docs
- [ ] Env-backed secrets are resolved via `resolveEnvVarsInObject` if needed

## Step 5: Validate Automatic Subscription Lifecycle

If the service supports programmatic webhook creation:

### createSubscription
- [ ] Calls the correct API endpoint to create a webhook
- [ ] Sends the correct event types/filters
- [ ] Passes the notification URL from `getNotificationUrl(ctx.webhook)`
- [ ] Returns `{ providerConfigUpdates: { externalId } }` with the external webhook ID
- [ ] Throws on failure (orchestration handles rollback)
- [ ] Provides user-friendly error messages (401 → "Invalid API Key", etc.)

### deleteSubscription
- [ ] Calls the correct API endpoint to delete the webhook
- [ ] Handles 404 gracefully (webhook already deleted)
- [ ] Never throws — catches errors and logs non-fatally
- [ ] Skips gracefully when `apiKey` or `externalId` is missing

### Orchestration Isolation
- [ ] NO provider-specific logic in `route.ts`, `provider-subscriptions.ts`, or `deploy.ts`
- [ ] All subscription logic lives on the handler (`createSubscription`/`deleteSubscription`)

## Step 6: Validate Registration and Block Wiring

### Trigger Registry (`triggers/registry.ts`)
- [ ] All triggers are imported and registered
- [ ] Registry keys match trigger IDs exactly
- [ ] No orphaned entries (triggers that don't exist)

### Provider Handler Registry (`providers/registry.ts`)
- [ ] Handler is imported and registered (if handler exists)
- [ ] Registry key matches the `provider` field on the trigger configs
- [ ] Entries are in alphabetical order

### Block Wiring (`blocks/blocks/{service}.ts`)
- [ ] Block has `triggers.enabled: true`
- [ ] `triggers.available` lists all trigger IDs
- [ ] All trigger subBlocks are spread into `subBlocks`: `...getTrigger('id').subBlocks`
- [ ] No trigger IDs in `triggers.available` that aren't in the registry
- [ ] No trigger subBlocks spread that aren't in `triggers.available`

## Step 7: Validate Security

- [ ] Webhook secrets are never logged (not even at debug level)
- [ ] Auth verification runs before any event processing
- [ ] No secret comparison uses `===` (must use `safeCompare` or `crypto.timingSafeEqual`)
- [ ] Timestamp/replay protection is reasonable (not too tight for retries, not too loose for security)
- [ ] Raw body is used for signature verification (not re-serialized JSON)

## Step 8: Report and Fix

### Report Format

Group findings by severity:

**Critical** (runtime errors, security issues, or data loss):
- Wrong HMAC algorithm or header name
- `formatInput` keys don't match trigger `outputs`
- Missing `verifyAuth` when the service sends signed webhooks
- `matchEvent` returns non-boolean values
- Provider-specific logic leaking into shared orchestration files
- Trigger IDs mismatch between trigger files, registry, and block
- `createSubscription` calling wrong API endpoint
- Auth comparison using `===` instead of `safeCompare`

**Warning** (convention violations or usability issues):
- Missing `extractIdempotencyId` when the service provides delivery IDs
- Timestamps in idempotency keys (breaks dedup on retries)
- Missing challenge handling when the service requires URL verification
- Output schema missing fields that `formatInput` returns (undiscoverable data)
- Overly tight timestamp skew window that rejects legitimate retries
- `matchEvent` not filtering challenge/verification events
- Setup instructions missing important steps

**Suggestion** (minor improvements):
- More specific output field descriptions
- Additional output fields that could be exposed
- Better error messages in `createSubscription`
- Logging improvements

### Fix All Issues

After reporting, fix every **critical** and **warning** issue. Apply **suggestions** where they don't add unnecessary complexity.

### Validation Output

After fixing, confirm:
1. `bun run type-check` passes
2. Re-read all modified files to verify fixes are correct
3. Provider handler tests pass (if they exist): `bun test {service}`

## Checklist Summary

- [ ] Read all trigger files, provider handler, types, registries, and block
- [ ] Pulled and read official webhook/API documentation
- [ ] Validated trigger definitions: options, instructions, extra fields, outputs
- [ ] Validated primary/secondary trigger distinction (`includeDropdown`)
- [ ] Validated provider handler: auth, matchEvent, formatInput, idempotency
- [ ] Validated output alignment: every `outputs` key ↔ every `formatInput` key
- [ ] Validated subscription lifecycle: createSubscription, deleteSubscription, no shared-file edits
- [ ] Validated registration: trigger registry, handler registry, block wiring
- [ ] Validated security: safe comparison, no secret logging, replay protection
- [ ] Reported all issues grouped by severity
- [ ] Fixed all critical and warning issues
- [ ] `bun run type-check` passes after fixes
Loading
Loading