Skip to content

Commit c94a41d

Browse files
khaliqgantclaude
andauthored
feat(adapters): tier-1 batch 2 — asana, clickup, intercom, zendesk (#40)
* feat(adapters): scaffold tier-1 batch 2 — asana, clickup, intercom, zendesk Adds 4 Tier-1 SaaS adapter packages with full implementation, mirroring the batch-1 shape (hubspot/salesforce/pipedrive/jira): - @relayfile/adapter-asana (PM; X-Hook-Signature HMAC-SHA256, two-phase handshake) - @relayfile/adapter-clickup (PM; X-Signature HMAC-SHA256) - @relayfile/adapter-intercom (Support; X-Hub-Signature HMAC-SHA1) - @relayfile/adapter-zendesk (Support; X-Zendesk-Webhook-Signature-256 HMAC-SHA256, 5-min tolerance) Each package follows the @relayfile/adapter-linear shape: - <slug>-adapter.ts extending IntegrationAdapter (ingestWebhook, computePath, computeSemantics, per-object helpers) - path-mapper.ts (deterministic VFS paths) - queries.ts + writeback.ts (read/write API mappings) - webhook-normalizer.ts (real createHmac + timingSafeEqual) - types.ts (config + payload types) - tests covering accept-valid + reject-tampered signature paths Per-package gates passed: - tsc --noEmit clean for all 4 packages - npm test passing: asana 12/12, clickup 12/12, intercom 14/14, zendesk 12/12 - Required route anchors present in code - Line floors met (adapter.ts ≥ 400 lines, webhook-normalizer.ts ≥ 200 lines) Also registers the 4 packages in .github/workflows/publish.yml per the "Adding a new adapter package" convention in AGENTS.md. Follow-ups (separate PRs): batches 3 & 4 (8 more T1 SaaS adapters), then the catalog finalize PR. Verify pass against these 4 packages will run before merge to catch any signature-scheme drift like the salesforce bug caught in PR #38. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(zendesk): correct webhook signature header name + empty-body handling The verify pass against batch 2 flagged this as a blocker: our code looked up the signature in 'X-Zendesk-Webhook-Signature-256', but Zendesk's verifying-webhooks reference (and the NangoHQ template) name the actual header 'X-Zendesk-Webhook-Signature' (no '-256' suffix). As written, validateZendeskWebhookSignature() would have returned reason='missing- signature' for every real Zendesk delivery in production. Despite the algorithm being SHA-256, the header name does not include the suffix. This is a frequent source of bugs. Changes: - Renamed ZENDESK_SIGNATURE_256_HEADER -> ZENDESK_SIGNATURE_HEADER with the correct value 'X-Zendesk-Webhook-Signature'. - Kept the old export name as a deprecated alias so any external caller importing it continues to compile but resolves to the right header. - toRawBodyBuffer now returns Buffer.alloc(0) for null/undefined raw payloads instead of falling back to JSON.stringify (which produced the literal string 'undefined' or 'null' and would mismatch a true empty body sent on GET/DELETE webhook deliveries). Tests: 12/12 passing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(intercom): correct writeback HTTP methods (auto-fixed by ricky) The verify pass against batch 2 caught two writeback method bugs in @relayfile/adapter-intercom; ricky's new code-drift auto-fix path dispatched a code-fix agent that patched them in place, then the re-verify came back clean (verdict=PASS for all 4 batch-2 adapters). Changes against Intercom's actual REST API: - update_conversation: PATCH -> PUT Intercom's /conversations/:id endpoint is documented as PUT for updates, not PATCH. PATCH would 405 in production. - update_company: PUT /companies/:id -> POST /companies (upsert) Intercom does not expose PUT /companies/:id. Companies are upserted via POST /companies keyed by company_id in the request body. Updated method + endpoint accordingly. Tests: 14/14 still passing. This is the first end-to-end test of ricky PR #69 (auto-fix code drift). The fix → restart-from-root → re-verify cycle worked as designed: attempt 1 found drift, agent edited writeback.ts in place, attempt 2 re-ran the verify agents against the patched source and got PASS. "Auto-fix: repaired after 2/7 attempt(s)" in the run summary. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(adapters): address PR review feedback * fix(adapters): address remaining PR #40 review findings [Critical, zendesk] Test fixture used millisecond timestamp; production breaks Zendesk's verifying-webhooks reference documents the X-Zendesk-Webhook-Signature-Timestamp header as ISO 8601 UTC (e.g. "2021-03-25T05:09:27Z"). The HMAC input is the raw header string concatenated with the body. The previous test fixture used '1710000000000' (millisecond string). The validator parses both formats for the freshness check, but the HMAC was computed against the millisecond literal — meaning the test never validated the actual format Zendesk sends. In production, signature verification would fail on every real webhook because the computed HMAC wouldn't match (test signs against ms; provider signs against ISO 8601). Fixture now uses "2024-01-15T12:00:00Z" with the correctly recomputed signature. Introduced timestampEpochMs constant for the now-arithmetic the tests do (Number('2024-01-15T12:00:00Z') is NaN). Same change opportunistically swaps tests off the deprecated ZENDESK_SIGNATURE_256_HEADER import (added in b4a8b86 with a deprecation notice) onto ZENDESK_SIGNATURE_HEADER. Header value is identical; intent now matches the canonical export. [Major, clickup] Restrict signature input type from `unknown` to raw body computeClickUpWebhookSignature accepted `unknown`; toRawBodyBuffer silently fell back to JSON.stringify for already-parsed objects. Re-serializing produces bytes that differ from the original request (whitespace, key order), so the HMAC mismatches even when the secret is right. Tightened input type to ClickUpWebhookRawBody (string | Buffer | Uint8Array | ArrayBuffer); fallback now throws a clear error for callers who slip past the type system via `as any`. [Minor] Stop tracking .trajectories/ runtime state Added .trajectories/ to .gitignore and removed the two tracked files. Local agent runtime state should not appear in feature PR diffs. Skipped findings (with rationale): - "Update lockfile for new workspaces" (P1 from chatgpt-codex): package-lock.json was already updated in commit b4a8b86 when running `npm install --workspace=@relayfile/adapter-zendesk` brought all four batch-2 packages into the lockfile as workspaces. Verified: `grep '"packages/(asana|clickup|intercom|zendesk)"' package-lock.json` matches all four. - "Don't bump version in feature PR" for intercom (Major from coderabbit): the new packages all start at version 0.1.0, which matches the established pattern from PR #38 batch-1 (hubspot, salesforce, pipedrive, jira also started at 0.1.0 and were bumped to 0.1.1 by the post-merge release commit a02e7ca). Changing only intercom would create inconsistency. The publish workflow continues to own the bump. Tests across all 4 batch-2 packages: 54/54 passing. asana 13/13 clickup 13/13 intercom 15/15 zendesk 13/13 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a02e7ca commit c94a41d

49 files changed

Lines changed: 12466 additions & 290 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/publish.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ on:
2020
- salesforce
2121
- pipedrive
2222
- jira
23+
- asana
24+
- clickup
25+
- intercom
26+
- zendesk
2327
default: "all"
2428
version:
2529
description: "Version bump type"
@@ -84,7 +88,7 @@ jobs:
8488
# Keep this list in sync with the `package` input options above and
8589
# the directories under packages/. See AGENTS.md → "Adding a new
8690
# adapter package" for the checklist that gates new entries here.
87-
echo "packages=core github gitlab teams slack linear notion hubspot salesforce pipedrive jira" >> "$GITHUB_OUTPUT"
91+
echo "packages=core github gitlab teams slack linear notion hubspot salesforce pipedrive jira asana clickup intercom zendesk" >> "$GITHUB_OUTPUT"
8892
else
8993
echo "packages=${{ github.event.inputs.package }}" >> "$GITHUB_OUTPUT"
9094
fi

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ packages/*/tests/**/*.js.map
1010
packages/*/tests/**/*.d.ts.map
1111
.claude/settings.json
1212
.mcp.json
13+
.trajectories/

.trajectories/active/traj_829pqp6emgql.json

Lines changed: 0 additions & 46 deletions
This file was deleted.

.trajectories/index.json

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)