Skip to content

Ask the same source questions in both nodes - #16

Open
leggetter wants to merge 2 commits into
mainfrom
feat/source-config-parity
Open

Ask the same source questions in both nodes#16
leggetter wants to merge 2 commits into
mainfrom
feat/source-config-parity

Conversation

@leggetter

Copy link
Copy Markdown
Contributor

The problem

Source → Get or Create offered Source Type and a raw JSON config field. The trigger, which creates sources in the same project, had labelled fields for every verification scheme. So creating a verified Stripe source from the action node meant hand-writing:

{"auth_type":"STRIPE","auth":{"webhook_secret_key":"whsec_..."}}

Source Config (JSON) is documented as "advanced", but for any platform source it was the only route.

Trigger Action node (before) Action node (after)
Source Type
Verification mode
Platform secret JSON only
HMAC secret / header / algorithm / encoding JSON only
API key header + value JSON only
Basic auth user + password JSON only

How

The fields move to descriptions/SourceProperties.ts and both nodes spread them in.

n8n has no way to add a displayOptions.show condition to a property from outside it, so the shared factory takes the extra conditions and merges them into each field. The trigger shows these unconditionally; the action node needs them gated on resource and operation.

buildSourceConfig now types its context structurally instead of as IHookFunctions. The trigger reads parameters without an item index and the action node reads them with one, so the action node passes a shim that closes over its index. Narrowing the type rather than changing the signature leaves the twelve existing call sites in the test suite untouched.

Config is omitted from the create body when nothing is configured — config: {} is not the same as absent, and would ask Hookdeck to blank it.

Testing

npm run lint 0 errors, 2 warnings (the accepted icon ones)
npm run build pass
npm run scan pass
verify-package-load.mjs 29 checks
node --test test/unit.test.mjs 110/110

The trigger's properties are byte-identical before and after. I built the tree both ways, loaded both node descriptions, and diffed them — the trigger half is unchanged, and the action node gains exactly ten fields and loses none. That was the main regression risk in moving a 157-line block between files.

Verified against the live API, not only the mocks, since the mocks would happily accept a config shape Hookdeck rejects:

Stripe, labelled field only  -> type=STRIPE  authenticated=true   auth.webhook_secret_key set
Generic + HMAC, labelled     -> type=WEBHOOK authenticated=true   all four HMAC fields present
Generic, no verification     -> type=WEBHOOK authenticated=false  no auth

Three new unit tests cover the field path, the JSON escape hatch still winning where they overlap, and config being omitted rather than sent empty.

Notes

No version bump, per CONTRIBUTING.md. This is additive — new optional fields, no renames — so 0.3.0.

This is the first of the two priorities discussed. The second, the clunkiness around Update Existing Source (#14), is deliberately not here. Worth noting the two interact: with this change, a properly typed source can be created up front, so the adopt-an-existing-source-then-reconfigure path gets hit far less often. That should make #14 easier to judge.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XtT85W8PPr2S8RW2WhCtpi

leggetter and others added 2 commits August 26, 2026 10:34
Source > Get or Create offered Source Type and a raw JSON config field, so
creating a verified source there meant hand-writing

  {"auth_type":"STRIPE","auth":{"webhook_secret_key":"..."}}

while the trigger, which creates sources for the same project, had a labelled
Webhook Secret field for exactly that. The JSON field was documented as
"advanced", but for any platform source it was the only route.

The verification fields move to descriptions/SourceProperties.ts and both nodes
spread them in. n8n has no way to add a `displayOptions.show` condition from
outside a property, so the shared factory takes the extra conditions and merges
them: the trigger shows these unconditionally, the action node needs them gated
on resource and operation.

buildSourceConfig now types its context structurally rather than as
IHookFunctions. The trigger reads parameters without an item index and the
action node reads them with one, so the action node passes a shim that closes
over its index. Narrowing the type rather than changing the signature leaves
the twelve existing call sites in the test suite untouched.

Config is omitted from the create body when nothing is configured. An empty
object is not the same as absent — `config: {}` asks Hookdeck to blank it.

Verified against the live API rather than only the mocks: a Stripe source
created from the labelled field comes back authenticated with the secret set, an
HMAC source carries all four fields, and a source with verification off comes
back unauthenticated with no auth.

The trigger's own properties are byte-identical before and after, checked by
diffing the loaded description objects across both builds.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XtT85W8PPr2S8RW2WhCtpi
The new fields are only worth having if the secret reaches Hookdeck, and the
API cannot answer that: a platform source never echoes `auth_type`, configured
or not, so one holding a secret and one holding none come back identical. The
only signal is `verified` on an inbound request.

So the test signs a payload with the secret it supplied and sends a second one
unsigned, and asserts Hookdeck's verdict on each. That distinguishes a secret
that was applied from one that was accepted and quietly dropped, which is the
failure worth catching here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants