Skip to content

feat(core): rename data-defined internals, give webhook checks the raw body, real HubSpot components - #699

Open
seanspeaks wants to merge 8 commits into
claude/shared-conversation-8hgmbr-stack-7-manifest-auditfrom
claude/shared-conversation-8hgmbr-stack-8-raw-body-webhooks
Open

seanspeaks wants to merge 8 commits into
claude/shared-conversation-8hgmbr-stack-7-manifest-auditfrom
claude/shared-conversation-8hgmbr-stack-8-raw-body-webhooks

Conversation

@seanspeaks

@seanspeaks seanspeaks commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Stack 8 of 9. Stacked on #698.

Summary

  • Rename. integrations/data-defined/ becomes integrations/definitions/, data-defined-integration.js becomes integration-runtime.js, and the env vars move to INTEGRATION_DEFINITIONS_*. A published integration is just an integration, so its internals no longer say "data-defined". The diff is mostly moved files.
  • Signature checks get exact bytes. HubSpot, Slack, Stripe and Linear sign the exact body bytes; HubSpot v3 also signs the method and public URL. Until now, verification received only the parsed body.
    • The HTTP app keeps req.rawBody.
    • onWebhookReceived queues the method, the public URL (from x-forwarded-proto/host plus originalUrl) and the raw body, up to 96 KB.
    • Above 96 KB the body is left out and verification fails closed. SQS messages are capped at 256 KB.
    • webhookVerificationInput(data) gives a code integration the same values.
    • Eight modules' webhook blocks are no longer unimplemented. They need the api-module-library release from feat(webhooks): verifyWebhookSignature on eight modules, and fix HubSpot updateDeal api-module-library#105.
    • Salesforce has no signed push webhook, so its deliveries are rejected.
  • HubSpot components checked against @hubspot/ui-extensions 0.17.1 (the package's d.ts files). Most names were right. Fixed:
    • EmptyState takes its text as children.
    • A button's action is now a node-level field, not a prop.
    • open_url uses the real href prop.
    • A test pins the emitted components and prop values to 0.17.1.

Test plan

  • Same 31 pre-existing failures as next at this commit. Nothing new fails.
  • Tests for raw-body capture, the 96 KB fail-closed path, and the HubSpot component allowlist (four mutations killed).
  • One real webhook delivery per vendor in dev.

Generated by Claude Code


Note

High Risk
Breaking API/path and config-type renames plus webhook acceptance changes (raw body, size limit, and stricter verify) can reject or mishandle deliveries until modules and proxies are aligned.

Overview
Renames the definition-based integration stack from data-defined to integrations/definitions and IntegrationRuntime, including catalogue route GET /api/integration-definitions, shared host type integration-runtime, and test env vars INTEGRATION_DEFINITIONS_*. ADRs 013/030/063 are updated to match the new vocabulary.

Webhook verification now preserves req.rawBody in the HTTP layer and queues method, public URL, and raw body (capped at 96 KB, fail-closed beyond that) through onWebhookReceived and the definition runtime’s manifest verify. webhookVerificationInput exposes the same shape to code integrations. Capability manifests drop “unimplemented” on eight vendors’ verifyWebhookSignature (pending api-module-library release); Salesforce stays rejected.

HubSpot preview output is aligned with @hubspot/ui-extensions 0.17.1: EmptyState text as children, userAction on a node-level action, open_url via href, plus allowlist tests.

Reviewed by Cursor Bugbot for commit 0d57ee8. Bugbot is set up for automated code reviews on this repo. Configure here.

📦 Published PR as canary version: 2.0.0--canary.699.0d57ee8.0

✨ Test out this PR locally via:

npm install @friggframework/admin-scripts@2.0.0--canary.699.0d57ee8.0
npm install @friggframework/core@2.0.0--canary.699.0d57ee8.0
npm install @friggframework/devtools@2.0.0--canary.699.0d57ee8.0
npm install @friggframework/eslint-config@2.0.0--canary.699.0d57ee8.0
npm install @friggframework/prettier-config@2.0.0--canary.699.0d57ee8.0
npm install @friggframework/schemas@2.0.0--canary.699.0d57ee8.0
npm install @friggframework/serverless-plugin@2.0.0--canary.699.0d57ee8.0
npm install @friggframework/test@2.0.0--canary.699.0d57ee8.0
npm install @friggframework/ui@2.0.0--canary.699.0d57ee8.0
# or 
yarn add @friggframework/admin-scripts@2.0.0--canary.699.0d57ee8.0
yarn add @friggframework/core@2.0.0--canary.699.0d57ee8.0
yarn add @friggframework/devtools@2.0.0--canary.699.0d57ee8.0
yarn add @friggframework/eslint-config@2.0.0--canary.699.0d57ee8.0
yarn add @friggframework/prettier-config@2.0.0--canary.699.0d57ee8.0
yarn add @friggframework/schemas@2.0.0--canary.699.0d57ee8.0
yarn add @friggframework/serverless-plugin@2.0.0--canary.699.0d57ee8.0
yarn add @friggframework/test@2.0.0--canary.699.0d57ee8.0
yarn add @friggframework/ui@2.0.0--canary.699.0d57ee8.0

…ations

Rename the data-defined folder, class, route and names to integration
runtime / definitions. Migration directories are untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGC9SnFuqdjX2xH2qeu8vw
Vendors sign exact bytes (HubSpot, Slack, Stripe, Linear) and HubSpot v3 also
signs the method and public URL; the runtime handed verify only the parsed
body, so every check would fail once modules implement it
(api-module-library 659b90d does, for eight modules).

- The HTTP app keeps req.rawBody (a reference to the parsed buffer).
- IntegrationBase.onWebhookReceived queues method, public URL
  (x-forwarded-proto/host + originalUrl) and the raw body up to 96 KB;
  beyond that it is left out and a check needing it fails closed (SQS
  messages are capped at 256 KB). webhookVerificationInput(data) hands a
  code integration's module the same facts.
- The integration runtime passes rawBody, method and url to the manifest's
  verify, including through app-level fan-out.
- Manifests: the eight modules' webhook blocks are no longer unimplemented
  (they need the module release with 659b90d). Salesforce stays
  unimplemented: CDC arrives over a stream and Outbound Messages are
  unsigned, so a delivery there is rejected, never accepted unchecked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGC9SnFuqdjX2xH2qeu8vw
… it is built

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGC9SnFuqdjX2xH2qeu8vw
…d against @hubspot/ui-extensions 0.17.1)

EmptyState takes its text as children (it has no text prop and requires children); a userAction
button's action moves off props (not a Button prop) to a node-level field; open_url is the real
href prop. Adds an allowlist/prop-value test pinned to 0.17.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGC9SnFuqdjX2xH2qeu8vw

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization has no extra usage available to pay for this review.

If your organization's extra usage balance is empty, an organization admin can add extra usage credits at claude.ai/admin-settings/usage. If its monthly spend limit was reached, an admin can raise it on the same page. If neither applies, contact Anthropic support.

Once extra usage is available, someone with write access to this repository can comment @claude review on this pull request to trigger a review.

@seanspeaks seanspeaks added release Create a release when this pr is merged prerelease This change is available in a prerelease. labels Oct 19, 2026 — with Claude
@seanspeaks

Copy link
Copy Markdown
Contributor Author

ADR reconciliation needed after Stack A/B — drafted with Claude Code at Sean's request

Severity: cross-ref only.

…, one input

Section 14: record the 96 KB raw-body limit and the fail-closed behaviour,
and that webhookVerificationInput should be the one input for ADR-054
contract-2 verifiers as well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGC9SnFuqdjX2xH2qeu8vw
…ier levels), carried into definitions/ and integration-runtime.js; triggers, neutral names and the admin route registry under the new names

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGC9SnFuqdjX2xH2qeu8vw
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGC9SnFuqdjX2xH2qeu8vw
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

prerelease This change is available in a prerelease. release Create a release when this pr is merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants