Repository navigation
Add first-party n8n, Make, Zapier and Pipedream integrations #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
purpshell
wants to merge
14
commits into
main
Choose a base branch
from
feat/automation-integrations
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+35,610
−0
Open
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
f768cb2
Add SDK-aligned automation adapters for four platforms
purpshell d18d9bd
Use explicit icon colors for n8n themes
purpshell 4c660b8
Keep Make media validation within documented JavaScript globals
purpshell 19c3683
Add scoped Make authoring access check
purpshell 9dae5e3
fix: address native integration and publishing review findings
purpshell 9915045
Preserve webhook creation generations and native edge cases
purpshell 5ede700
Create SDK drift test fixtures under the system temp directory
purpshell b2b91a2
Gate n8n publication on the whole reviewed tree before repository cod…
purpshell 29b8943
Fail the generated-file check on files the generator no longer emits
purpshell 46dd052
Generate a webhook creation nonce per trigger activation
purpshell c403f63
Make: match unusual hook URLs like shared code and detach by webhook ID
purpshell 20b3534
Zapier: read hook headers in the documented Http- prefixed form
purpshell b8bc1db
Let the n8n inbound handoff recipe activate as imported
purpshell bf30f04
Keep write recovery state in errors and n8n Continue On Fail items
purpshell File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| name: Integration checks | ||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: [main] | ||
| permissions: | ||
| contents: read | ||
| jobs: | ||
| contracts-and-adapters: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | ||
| with: | ||
| node-version-file: .nvmrc | ||
| cache: npm | ||
| - run: npm install --global npm@11.20.0 | ||
| - run: npm ci --ignore-scripts --no-audit | ||
| - run: npm run check | ||
| - run: npm run lint --workspace n8n-nodes-polymorfa | ||
| - run: npm run validate:zapier | ||
| - run: npm run check:sdk | ||
| - run: node scripts/check-upstream.mjs --pinned | ||
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | ||
| with: | ||
| node-version: '22.23.2' | ||
| - run: node --test --test-reporter=spec tests/*.test.cjs tests/*.test.mjs |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| name: Publish n8n package | ||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| description: Reviewed package version | ||
| required: true | ||
| type: string | ||
| reviewed-source: | ||
| description: Immutable reviewed source commit from the approved release receipt | ||
| required: true | ||
| type: string | ||
| permissions: | ||
| contents: read | ||
| jobs: | ||
| verify: | ||
| # Runs repository code, so it never receives an OIDC token. | ||
| if: github.ref == 'refs/heads/main' | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| ref: ${{ github.sha }} | ||
| persist-credentials: false | ||
| # Gate first: nothing else from the repository runs before the source binding is checked. | ||
| - run: node scripts/release-gate.mjs | ||
| env: | ||
| RELEASE_VERSION: ${{ inputs.version }} | ||
| RELEASE_REVIEWED_SOURCE: ${{ inputs.reviewed-source }} | ||
| RELEASE_REF: ${{ github.ref }} | ||
| RELEASE_SOURCE: ${{ github.sha }} | ||
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | ||
| with: | ||
| node-version-file: .nvmrc | ||
| - run: npm install --global npm@11.20.0 | ||
| - run: npm ci --ignore-scripts --no-audit | ||
| - run: npm run check | ||
| - run: npm run lint --workspace n8n-nodes-polymorfa | ||
| - run: npm run check:sdk | ||
| publish: | ||
| needs: verify | ||
| if: github.ref == 'refs/heads/main' | ||
| runs-on: ubuntu-latest | ||
| environment: npm-release | ||
| permissions: | ||
| contents: read | ||
| id-token: write | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| ref: ${{ github.sha }} | ||
| persist-credentials: false | ||
| # Git and jq only. This runs before any repository file is executed or read as configuration | ||
| # (.nvmrc, .npmrc, package scripts), because this job can mint an npm OIDC token. | ||
| - name: Check reviewed source binding | ||
| shell: bash | ||
| env: | ||
| RELEASE_VERSION: ${{ inputs.version }} | ||
| RELEASE_REVIEWED_SOURCE: ${{ inputs.reviewed-source }} | ||
| RELEASE_REF: ${{ github.ref }} | ||
| RELEASE_SOURCE: ${{ github.sha }} | ||
| run: | | ||
| set -euo pipefail | ||
| [[ "$RELEASE_REF" == refs/heads/main ]] | ||
| [[ "$RELEASE_SOURCE" =~ ^[a-f0-9]{40}$ && "$RELEASE_REVIEWED_SOURCE" =~ ^[a-f0-9]{40}$ ]] | ||
| [[ "$(git rev-parse HEAD)" == "$RELEASE_SOURCE" ]] | ||
| [[ "$RELEASE_VERSION" =~ ^[0-9A-Za-z.+-]+$ ]] | ||
| [[ "$(git show HEAD:n8n/package.json | jq -r .version)" == "$RELEASE_VERSION" ]] | ||
| receipt="$(git show "HEAD:releases/$RELEASE_VERSION.json" | jq -r .reviewedSource)" | ||
| [[ "$receipt" == "$RELEASE_REVIEWED_SOURCE" ]] | ||
| git merge-base --is-ancestor "$RELEASE_REVIEWED_SOURCE" HEAD | ||
| # Everything except release receipts must match the reviewed source. | ||
| git diff --exit-code "$RELEASE_REVIEWED_SOURCE" HEAD -- . ':(exclude)releases' | ||
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | ||
| with: | ||
| node-version-file: .nvmrc | ||
| registry-url: https://registry.npmjs.org | ||
| - run: npm install --global npm@11.20.0 | ||
| - run: npm ci --ignore-scripts --no-audit | ||
| - run: npm run build | ||
| - run: npm publish --workspace n8n-nodes-polymorfa --provenance --access public | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| name: SDK drift | ||
| on: | ||
| workflow_dispatch: | ||
| schedule: | ||
| - cron: '23 8 * * 1' | ||
| permissions: | ||
| contents: read | ||
| jobs: | ||
| check-reviewed-contract: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | ||
| with: | ||
| node-version-file: .nvmrc | ||
| - run: node scripts/check-upstream.mjs |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| save-exact=true | ||
| fund=false |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 24.15.0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| # Changelog | ||
|
|
||
| ## Unreleased | ||
|
|
||
| - Separate webhook receiver secrets from public marker/idempotency metadata. | ||
| - Remove the Webhook Creation Key field from all triggers. Each activation uses | ||
| its own adapter-generated nonce, so off/on, n8n test listening and Pipedream | ||
| redeploys work, and a receipt for a deleted webhook is refused. | ||
| - Make: detach reads the recorded webhook by ID; unusual URLs on unrelated | ||
| project webhooks no longer break attach. | ||
| - Zapier: accept the documented `Http-` prefixed raw request header form. | ||
| - n8n Continue On Fail items include `code`, `status`, `requestId` and | ||
| `retryAfter`. Server errors on writes keep the reconcile guidance. | ||
| - The n8n inbound handoff recipe derives its subscription key from the workflow ID. | ||
| - Preserve definite subscription errors and non-JSON uncertain outcomes; | ||
| normalize callback ownership and native Zapier response headers. | ||
| - Keep successful n8n batch items when Continue On Fail is enabled. Require | ||
| saved notification identities before recipe sends and write identities in Zapier. | ||
| - Restrict n8n publication dispatch to main and bind its reviewed source receipt. | ||
|
|
||
| - First-party source for n8n, Make, Zapier and Pipedream with a common public API | ||
| and SDK contract pin. | ||
| - Text/replies, templates, URL/base64 media, reactions, Number/template lookup | ||
| and allowlisted API calls. n8n also maps native binary inputs. | ||
| - Owned project-webhook subscriptions for messages, message state, Number state | ||
| and completed calls, with authenticated receivers and stable event identity. | ||
| - Explicit recovery for completed/uncertain writes and conservative retry age. | ||
| - Contract/generation checks, SDK drift detection and provider release records. | ||
|
|
||
| This is development source. No registry publication, provider approval or public | ||
| marketplace listing is established. Functions and message-operation lookup are | ||
| excluded until their public contracts are accepted. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| # Maintain the integrations with the SDKs | ||
|
|
||
| Use Node 24.15.0 and npm 11.20.0 for the build tools. The generated JavaScript is | ||
| also checked on Node 22.23.2 for the Zapier execution boundary. These checks do | ||
| not establish the versions deployed by a provider. | ||
|
|
||
| ```sh | ||
| npm ci --ignore-scripts | ||
| npm run check | ||
| npm run lint --workspace n8n-nodes-polymorfa | ||
| npm run validate:zapier | ||
| npm run check:sdk | ||
| node scripts/check-upstream.mjs --pinned | ||
| ``` | ||
|
|
||
| `shared/` owns the action fields, event groups, request mapping and recovery | ||
| behavior. `npm run generate` copies that code into independently deployable | ||
| native packages and generates Make functions and Pipedream components. Do not | ||
| edit generated files directly. CI rejects stale generated output, including | ||
| files in generated directories that the generator no longer emits; `npm run | ||
| generate` removes them. | ||
|
|
||
| `contracts/source.json` pins the public API audience and matching SDK source. | ||
| `coverage.json` identifies each allowed operation and deliberate exclusions. | ||
| The public snapshots contain only these operations and their referenced schemas. | ||
| Do not import the complete management API or an SDK's extra operation catalog. | ||
|
|
||
| The SDK's baseline also contains fields outside this public audience, including | ||
| transport selection. The adapters do not expose them. `check:sdk` validates the | ||
| actual request cases against the pinned SDK schemas. `sdk-baseline.json` records | ||
| the corresponding reviewed SDK fragment fingerprints. `check:upstream` compares | ||
| them to current SDK `main`; its scheduled workflow reports changes without | ||
| repinning, publishing or creating an app. The pinned check is reproducible even | ||
| when SDK `main` advances. | ||
|
|
||
| For a relevant API/SDK change, update the accepted public snapshot, source/hash | ||
| metadata, coverage and every affected adapter. Add an exclusion with its reason | ||
| when a capability is intentionally unavailable. Test errors, IDs, media, hooks, | ||
| pagination and uncertain writes where affected. Regenerate all packages and | ||
| update native recipe mappings. Keep one integrations PR for that feature cycle. | ||
|
|
||
| Record real provider tests separately from these local fixtures. Include exact | ||
| source/app versions and the accepted API revision. Update the owning product | ||
| feature, issue, release record, customer documentation and provider submission. | ||
| Source merge, package publication, app review and public listing are distinct. | ||
|
|
||
| The n8n publication workflow is manual, uses npm provenance and requires recorded | ||
| receipts. Configure a protected `npm-release` environment and a Polymorfa-owned | ||
| npm trusted publisher before use. No provider account, environment protection or | ||
| trusted publisher has been configured by adding this workflow. Review is still | ||
| required; the gate is bookkeeping and does not authenticate human authorization. | ||
|
|
||
| Publication accepts only a `main` dispatch, checks out its immutable commit, and | ||
| requires the dispatch's reviewed-source commit to match the release receipt. Every | ||
| path except `releases/` must match the reviewed source, including tests, `.npmrc` | ||
| and `.nvmrc`. The `verify` job runs the gate before any install or test and has no | ||
| OIDC token. The `publish` job, which has `id-token: write`, repeats the check with | ||
| git and jq before Node setup, `.npmrc` use or any repository script. Restrict the `npm-release` environment to protected `main` | ||
| and require an independent release reviewer before enabling the trusted publisher. | ||
| These external settings cannot be secured by editable workflow code alone. | ||
|
|
||
| Webhook marker names, receiver verifiers and create-key seeds use separate HMAC | ||
| domains. The create key is `HMAC(markerKey, nonce)`. `hooks.activate` generates | ||
| a random nonce per activation and saves it in provider-private state before the | ||
| create: n8n node static data, Pipedream `$.service.db`, Zapier and Make in the | ||
| single `performSubscribe` call or attach run (neither platform offers state that | ||
| persists before those return). An uncertain retry of the same activation reuses | ||
| the nonce; a confirmed activation, a deletion or a replayed receipt for a deleted | ||
| webhook (`subscription_receipt_deleted`) clears it. Find-before-create and the | ||
| post-create live-ownership check stay in place. Users no longer enter a webhook | ||
| creation key. This is a change before the first release; no migration is implied. | ||
|
|
||
| Keep API credentials in each provider's credential store. Webhook receivers use | ||
| an authenticated per-subscription header supported by the public subscription | ||
| contract. A stable unique subscription key determines its private verifier. | ||
| Reactivation reuses its owned hook; another callback cannot reuse the key while | ||
| that hook exists. Changing a verifier or connection requires explicit lifecycle | ||
| and rotation testing. The adapters never emit signing secrets or add a relay. | ||
|
|
||
| All delivery channels can repeat events. Use the event ID in downstream dedupe | ||
| storage and a stable business key for effects. Zapier and Pipedream also use that | ||
| event ID in their native dedupe paths. No unbounded exactly-once claim is made. | ||
| Native n8n and Make consumers must persist their own processed-event IDs. | ||
|
|
||
| Revoking an API key does not delete an existing webhook endpoint. Disable/delete | ||
| the owned endpoint before withdrawing a connection, or remove it through an | ||
| authorized project management path if the key is already revoked. Never use a | ||
| broader credential automatically. Verify provider log redaction and callback | ||
| cleanup during acceptance, including failed cleanup and credential rotation. | ||
|
|
||
| Make uses provider-native custom IML functions, which require enablement by Make. | ||
| The generated JavaScript functions are tested, but their IML bindings, private | ||
| webhook-state mapping and attach/detach behavior require real platform acceptance. | ||
| Its attach preflight refuses inventories larger than one page instead of risking | ||
| a duplicate. Detach reads the recorded webhook by ID, so cleanup works in any | ||
| project size. Qualify attach pagination in Make before approving large-project | ||
| triggers. Its hook matching treats an unparseable URL as no match, as the shared | ||
| code does; a test runs both over the same inventories. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| The Polymorfa marks identify Polymorfa's service. The n8n icon uses the approved | ||
| Polymorfa website favicon. Trademark rights are separate from the MIT code license. | ||
|
|
||
| n8n, Make, Zapier and Pipedream are names of their respective providers. This | ||
| development repository does not claim provider certification or approval. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| { | ||
| "operations": { | ||
| "sendMessage": { | ||
| "contract": "messaging", | ||
| "method": "POST", | ||
| "path": "/messaging/{session}/messages/send", | ||
| "scope": "messages:write", | ||
| "sdkOperation": "sendMessage", | ||
| "purpose": "action" | ||
| }, | ||
| "sendReaction": { | ||
| "contract": "messaging", | ||
| "method": "POST", | ||
| "path": "/messaging/{session}/messages/react", | ||
| "scope": "messages:write", | ||
| "sdkOperation": "sendReaction", | ||
| "purpose": "action" | ||
| }, | ||
| "listProjectTemplates": { | ||
| "contract": "messaging", | ||
| "method": "GET", | ||
| "path": "/messaging/projects/{projectSlug}/templates", | ||
| "scope": "templates:read", | ||
| "sdkOperation": "listProjectTemplates", | ||
| "purpose": "action" | ||
| }, | ||
| "getProjectTemplate": { | ||
| "contract": "messaging", | ||
| "method": "GET", | ||
| "path": "/messaging/projects/{projectSlug}/templates/{id}", | ||
| "scope": "templates:read", | ||
| "sdkOperation": "getProjectTemplate", | ||
| "purpose": "action" | ||
| }, | ||
| "listPlatformSessions": { | ||
| "contract": "platform", | ||
| "method": "GET", | ||
| "path": "/platform/sessions", | ||
| "scope": "sessions:read", | ||
| "sdkOperation": "listPlatformSessions", | ||
| "purpose": "action" | ||
| }, | ||
| "listProjectWebhooks": { | ||
| "contract": "platform", | ||
| "method": "GET", | ||
| "path": "/platform/projects/{projectId}/webhooks", | ||
| "scope": "webhooks:read", | ||
| "sdkOperation": "listProjectWebhooks", | ||
| "purpose": "subscription lifecycle" | ||
| }, | ||
| "createProjectWebhook": { | ||
| "contract": "platform", | ||
| "method": "POST", | ||
| "path": "/platform/projects/{projectId}/webhooks", | ||
| "scope": "webhooks:manage", | ||
| "sdkOperation": "createProjectWebhook", | ||
| "purpose": "subscription lifecycle" | ||
| }, | ||
| "getProjectWebhook": { | ||
| "contract": "platform", | ||
| "method": "GET", | ||
| "path": "/platform/projects/{projectId}/webhooks/{webhookId}", | ||
| "scope": "webhooks:read", | ||
| "sdkOperation": "getProjectWebhook", | ||
| "purpose": "subscription lifecycle" | ||
| }, | ||
| "deleteProjectWebhook": { | ||
| "contract": "platform", | ||
| "method": "DELETE", | ||
| "path": "/platform/projects/{projectId}/webhooks/{webhookId}", | ||
| "scope": "webhooks:manage", | ||
| "sdkOperation": "deleteProjectWebhook", | ||
| "purpose": "subscription lifecycle" | ||
| } | ||
| }, | ||
| "platforms": [ | ||
| "n8n", | ||
| "make", | ||
| "zapier", | ||
| "pipedream" | ||
| ], | ||
| "excluded": { | ||
| "getMessageOperation": "Absent from published public Messaging export; SDK presence is insufficient.", | ||
| "runFunction": "Functions deliberately absent from published public Platform export." | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.