fix(actions): seed a flow action's params with the row id (#3915 follow-up) - #3934
Merged
Merged
Conversation
…ow-up) #3915 documented the REST actions endpoint's flow dispatch as "equivalent to POST /api/v1/automation/:target/trigger, without having to know the flow name". Invoking the CRM's real `crm_convert_lead` against a running server showed the claim did not hold: the params bag carried the record's fields — so `id` — but never `recordId`, so the flow's `get_lead` node died on `{recordId}` resolving to nothing, while the same flow triggered directly paused normally on its first screen. `dispatchFlowAction` now seeds the row id under the same keys the trigger route seeds (`recordId` + the `<objectName>Id` camelCase alias), plus the action's declared `recordIdParam` (sourced from `recordIdField`, default `id`) when it names a third key. Explicit action params still win over every seed. The MCP `run_action` path shares the helper and the fix. Only a live run could catch this: the unit tests mock `automation.execute`, so they pinned the call shape without noticing the bag lacked the key flows read. Regression tests now cover both seeded keys, a declared `recordIdParam`, a non-id `recordIdField`, explicit-param precedence, and the record-never-loaded case. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DTTKgYriDB6RVrkYjxxnG1
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 18 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Follow-up to #3919 / #3915. Found by dogfooding the merged fix against a running app, not by a test.
What the live run showed
#3919 gave
POST /api/v1/actions/:object/:actionits flow dispatch and documented it as "equivalent toPOST /api/v1/automation/:target/trigger, without having to know the flow name." Bootingexamples/app-crmand invoking its realcrm_convert_leadaction showed the claim did not hold.The params bag was built as
{ ...record, ...params }, so it carried the record'sidbut neverrecordId.ConvertLeadActiondeclaresrecordIdParam: 'recordId'and its flow reads{recordId}— a declared contract no dispatcher honoured, thedeclared ≠ enforcedshape in miniature. The MCPrun_actionpath had the identical gap; it just had never been pointed at a flow that reads{recordId}.The fix
New
seedFlowActionParams(shared by both headless surfaces viadispatchFlowAction) builds the bag in three layers, weakest first:isInputvariables the way the record-change trigger does;recordIdand the<objectName>IdcamelCase alias, the same twodomains/automation.tsseeds for the trigger route — plus the action's own declaredrecordIdParamwhen it names a third key, sourced fromrecordIdField(defaultid, per spec: a declaration may want a non-id value such astokenfor revoke-session);recordIdalso falls back to the id named in the URL when the record never loaded (new-record / unreadable-record invocations).Verification
Re-ran the same live invocation after rebuilding — the actions endpoint now returns the identical run the trigger route does:
{"success":true,"status":"paused","runId":"run_f61c12ff…", "screen":{"nodeId":"screen_account","objectName":"crm_account", "defaults":{"name":"Radium Labs"}, …}}defaults.nameis carried over from the lead, soget_leadresolved{recordId}and ran.Tests: 5 new regression cases (both seeded keys, a declared
recordIdParam, a non-idrecordIdField, explicit-param precedence, record-never-loaded). Full@objectstack/runtimesuite green — 53 files / 756 tests.Note on the test gap this exposed
#3919's unit tests mock
automation.execute, so they pinned the call shape without noticing the bag lacked the key flows actually read. The new cases assert the params bag contents specifically, but the durable lesson is that a mocked automation service cannot validate a flow contract — the live run is what caught this.🤖 Generated with Claude Code
https://claude.ai/code/session_01DTTKgYriDB6RVrkYjxxnG1
Generated by Claude Code