Skip to content

[One Workflow] Step registry completion context enhancement#260054

Merged
semd merged 18 commits intoelastic:mainfrom
semd:workflows/step_registry_completion_improvement
Apr 10, 2026
Merged

[One Workflow] Step registry completion context enhancement#260054
semd merged 18 commits intoelastic:mainfrom
semd:workflows/step_registry_completion_improvement

Conversation

@semd
Copy link
Copy Markdown
Contributor

@semd semd commented Mar 27, 2026

Summary

issue: https://github.com/elastic/security-team/issues/15982. (Resolves requirement #2)

Enriches SelectionContext with step values so that PropertySelectionHandler implementations (search, resolve, getDetails) can access sibling property values from the current step definition.

There are no existing steps using context.values yet — this is a prerequisite for upcoming steps from the Cases team that need to read sibling properties (e.g. owner) to scope their search/resolve logic.

What changed

SelectionContext.values — A new values field ({ config, input }) is populated from the step's YAML properties at the time search/resolve/getDetails are called. Handlers can now read sibling values like context.values.input.owner instead of having no visibility into the rest of the step.

YAML value extraction fixgetValueFromValueNode now handles non-scalar YAML nodes (arrays/sequences) via .toJSON(), fixing a bug where array properties like owner: [securitySolution] appeared as undefined in context.values.

Example — An example has been implemented in the examples.externalStep from the workflows_examples plugin (test with node scripts/kibana --dev --run-examples)

Demo

Gravacio.de.pantalla.2026-04-02.a.les.15.58.23.mov

Files changed

Area Files Change
Shared types kbn-workflows/types/v1.ts, latest.ts Added StepSelectionValues interface, values field on SelectionContext, generic type parameters on 4 interfaces
Step registry workflows_extensions/.../step_registry/types.ts Thread Config/Input schema types into StepPropertyHandler for automatic inference
Value builder build_workflow_lookup.ts Added buildStepSelectionValues() helper + fixed getValueFromValueNode for non-scalar nodes
Context wiring collect_all_custom_property_items.ts, get_custom_property_suggestions.ts Pass values when constructing SelectionContext
Docs STEPS.md Updated SelectionContext type definition and documented context.values
Tests build_workflow_lookup.test.ts, validate_custom_properties.test.ts, get_custom_property_suggestions.test.ts New tests for value building (including arrays), updated assertions for new context shape

@semd semd self-assigned this Mar 27, 2026
@semd semd requested a review from a team as a code owner March 27, 2026 16:37
@semd semd added release_note:skip Skip the PR/issue when compiling release notes backport:skip This PR does not require backporting Team:One Workflow Team label for One Workflow (Workflow automation) 9.4.0 labels Mar 27, 2026
@dej611 dej611 added v.9.4.0 and removed 9.4.0 labels Apr 2, 2026
Comment on lines 29 to 30
@@ -29,10 +31,16 @@
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is this still true?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This was never true, actually 😅
These changes don't make this type wrong, they just make getValueFromValueNode handle the reality. The type annotation is a pre-existing inaccuracy.
I updated the comment to note the special case here: 49520cc

The suggestion from Cursor:

That's ~37 usages across 12 files. Many of them access .valueNode.range, .valueNode.value, or pass it to APIs expecting Scalar. Widening the type to Scalar | YAMLSeq would require adding type guards or assertions at most of these sites — a significant scope expansion for this PR.
The current state is pragmatically correct: the type says Scalar, the comment says "can be a sequence at runtime," and getValueFromValueNode handles both. Worth cleaning up in a follow-up, but not here.

stepType: step.stepType,
scope,
propertyKey: key,
values: buildStepSelectionValues(step),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this would rebuild for every step properties.
Would it be possible to hoist this above the loop iteration and reuse its value?

Copy link
Copy Markdown
Contributor Author

@semd semd Apr 8, 2026

Choose a reason for hiding this comment

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

I don't think it is very likely to have more than one prop with selection configured in the same step. But won't hurt anyway, done here: 525d2a0

export async function validateCustomProperties(
customPropertyItems: CustomPropertyItem[]
): Promise<CustomPropertyValidationResult[]> {
clearCache();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

isn't this a bit aggressive? This could potentially impact also autocomplete

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeap, it is.
Actually, since we now pass all the values in the step definition to selection handlers, we would need to use the entire step definition as a cache key, and caching for selection search would become almost useless.

I think that with these changes, caching selection handlers on our side doesn't make sense anymore, because we don't know what values are being used by the registered steps to search the entries. It would be better to delegate the caching out to the selection handlers of the registered steps (other plugins), as they are the ones who know the values they use to search and resolve selection entries.

But I wanted to do it in a follow-up. This is an intermediate state to make things work properly. I'll explicitly remove the cache on our side in a separate PR (the result will be the same, since it is cleaned on every change), and I will notify all the teams about it.

Does it sound good?

if (!valueNode) return undefined;
if (YAML.isScalar(valueNode)) return valueNode.value;
if ('toJSON' in valueNode && typeof valueNode.toJSON === 'function') return valueNode.toJSON();
return (valueNode as { value?: unknown }).value;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is this branch reachable?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This branch is reached when the property is an array (YAMLSeq):

Captura de pantalla 2026-04-08 a les 11 27 00

if (current[seg] == null || typeof current[seg] !== 'object') {
current[seg] = {};
}
current = current[seg] as Record<string, unknown>;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

would it be possible to use the isRecord typeguard instead of the type casting?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yup! addressed here 76e2650

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

And fixed here 49c8d0e, we can use the isRecord, but we still need to cast it anyway down below...

@elasticmachine
Copy link
Copy Markdown
Contributor

💚 Build Succeeded

Metrics [docs]

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
workflowsManagement 2.2MB 2.2MB +648.0B

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
workflowsManagement 28.2KB 28.2KB -5.0B
Unknown metric groups

API count

id before after diff
@kbn/workflows 663 667 +4

History

cc @semd

@semd semd requested a review from dej611 April 8, 2026 14:59
@semd semd merged commit 28dce33 into elastic:main Apr 10, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:skip This PR does not require backporting release_note:skip Skip the PR/issue when compiling release notes Team:One Workflow Team label for One Workflow (Workflow automation) v9.4.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants