Skip to content

[Alert Triage workflow] Adds security.buildAlertEntityGraph and security.renderAlertNarrative…#259159

Merged
KDKHD merged 23 commits intoelastic:mainfrom
KDKHD:feature/alert-triage-steps-2
Apr 22, 2026
Merged

[Alert Triage workflow] Adds security.buildAlertEntityGraph and security.renderAlertNarrative…#259159
KDKHD merged 23 commits intoelastic:mainfrom
KDKHD:feature/alert-triage-steps-2

Conversation

@KDKHD
Copy link
Copy Markdown
Member

@KDKHD KDKHD commented Mar 23, 2026

… steps

Summary

Migrates two new workflow step definitions from feature/alert-false-positive-queue into this branch so they can be developed and shipped independently.

The two steps added are:

  • renderAlertNarrativeStepDefinition — renders a human-readable narrative for an alert based on its event category (process, network, file, DNS, authentication, cloud, registry, ML, threat match)
  • buildAlertEntityGraphStepDefinition — builds an entity relationship graph for an alert by querying related events and scoring entity connections

Both steps are registered behind the feature flag securitySolution.registerAlertValidationStepsEnabled (defaults to true) to allow safe removal of the flag at a later date without a code change. These 2 steps will be used by the alert false positive workflow in feature/alert-false-positive-queue

Changes

  • kibana.jsonc — adds workflowsManagement and workflowsExtensions as optional plugin dependencies
  • server/plugin_contract.ts / public/types.ts — adds WorkflowsExtensions types to setup/start dependency interfaces
  • common/constants.ts — adds REGISTER_ALERT_VALIDATION_STEPS_FEATURE_FLAG and PREINSTALLED_WORKFLOWS_FEATURE_FLAG constants
  • server/plugin.ts / public/plugin.tsx — registers step definitions on plugin setup, gated by the feature flag
  • server/workflows/step_types/render_alert_narrative_step/ — server-side step implementation with strategy pattern per event category
  • server/workflows/step_types/build_alert_entity_graph_step/ — server-side step implementation with entity graph traversal and scoring
  • public/workflows/step_types/render_alert_narrative_step/ — client-side step definition
  • public/workflows/step_types/build_alert_entity_graph_step/ — client-side step definition

Follow-up

Remove the REGISTER_ALERT_VALIDATION_STEPS_FEATURE_FLAG guard in server/workflows/step_types/register_workflow_steps.ts and public/workflows/step_types/register_workflow_steps.ts once the steps are ready to ship unconditionally.

Checklist

Check the PR satisfies following conditions.

Reviewers should verify this PR satisfies this list as well.

  • Any text added follows EUI's writing guidelines, uses sentence case text and includes i18n support
  • Documentation was added for features that require explanation or tutorials
  • Unit or functional tests were updated or added to match the most common scenarios
  • If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the docker list
  • This was checked for breaking HTTP API changes, and any breaking changes have been approved by the breaking-change committee. The release_note:breaking label should be applied in these situations.
  • Flaky Test Runner was used on any tests changed
  • The PR description includes the appropriate Release Notes section, and the correct release_note:* label is applied per the guidelines
  • Review the backport guidelines and apply applicable backport:* labels.

Identify risks

Does this PR introduce any risks? For example, consider risks like hard to test bugs, performance regression, potential of data loss.

Describe the risk, its severity, and mitigation for each identified risk. Invite stakeholders and evaluate how to proceed before merging.

@KDKHD KDKHD changed the title adds security.buildAlertEntityGraph and security.renderAlertNarrative… [Alert Triage workflow] Adds security.buildAlertEntityGraph and security.renderAlertNarrative… Mar 24, 2026
@KDKHD KDKHD marked this pull request as ready for review March 24, 2026 08:40
@KDKHD KDKHD requested a review from a team as a code owner March 24, 2026 08:40
@KDKHD KDKHD added release_note:skip Skip the PR/issue when compiling release notes backport:skip This PR does not require backporting labels Mar 24, 2026
@KDKHD KDKHD requested a review from a team as a code owner March 24, 2026 10:12
@botelastic botelastic Bot added the Team:One Workflow Team label for One Workflow (Workflow automation) label Mar 24, 2026
@KDKHD
Copy link
Copy Markdown
Member Author

KDKHD commented Mar 24, 2026

/ci

KDKHD and others added 2 commits April 1, 2026 16:01
git Merge branch 'main' of github.com:elastic/kibana into feature/alert-triage-steps-2
@KDKHD
Copy link
Copy Markdown
Member Author

KDKHD commented Apr 8, 2026

@elasticmachine merge upstream

@elasticmachine
Copy link
Copy Markdown
Contributor

merge conflict between base and head

Comment on lines +14 to +30
const inputSchema = z.object({
alertId: z.string().describe('The alert ID'),
alertIndex: z.string().describe('The index that contains the alert'),
});

const outputSchema = z.object({
alert_id: z.string(),
alert_index: z.string(),
timeline_string: z.string().describe('A Timeline-like English string for the alert'),
message: z.string(),
});

export const renderAlertNarrativeStepDefinition: PublicStepDefinition = {
id: 'security.renderAlertNarrative',
inputSchema,
outputSchema,
category: StepCategory.Elasticsearch,
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.

I'd recommend keeping the props that are shared between public and server registration in a common place. To avoid duplication and potentially drifting over time. The spec of the shared props is here

Also:

  • It would be interesting to add documentation on the server side as well, since it's going to be leveraged by the agent builder.
  • I see the feature flag. Consider adding stability: 'tech_preview'.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

label: 'Render Alert Narrative',
description:
'Render a human-readable narrative string for an alert based on its event, process, network, and host fields',
category: StepCategory.Elasticsearch,
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fix the category to be Kibana

@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented Apr 20, 2026

Catch flakiness early (recommended)

Recommended before merge: run the flaky test runner against this PR to catch flakiness early.

Trigger a run with the Flaky Test Runner UI or post this comment on the PR:

/flaky scoutConfig:src/platform/plugins/shared/workflows_extensions/test/scout/api/playwright.config.ts:30

This check is experimental. Share your feedback in the #appex-qa channel.

Posted via Macroscope — Flaky Test Runner nudge

@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented Apr 20, 2026

Scout Test Review

No issues found ✅

The two new entries in approved_step_definitions.ts follow the existing pattern correctly and are alphabetically sorted.

Share feedback in the #appex-qa channel.

Posted via Macroscope — Scout Test Review

Copy link
Copy Markdown
Contributor

@macroscopeapp macroscopeapp Bot left a comment

Choose a reason for hiding this comment

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

</antml :parameter>
[{"path": "src/platform/plugins/shared/workflows_extensions/test/scout/api/fixtures/approved_step_definitions.ts", "body": "🔵 Minor — Fixture maintainability\n\nThe file header states entries must be "alphabetically sorted", but the new security.* entries are placed before the cases.* block, which itself was already out of alphabetical order. Since the approval test iterates over registered steps and does a find() lookup, ordering doesn't affect correctness, but it does make the fixture harder to scan and maintain as the list grows.\n\nConsider moving cases.* entries to their correct alphabetical position (before data.*) so the full list follows the documented convention — or at minimum ensure security.* is placed after search.* and before any block that starts with a letter > s (which it currently is, so the new entries are correct relative to each other).\n\nThis is a pre-existing issue, not introduced by this PR. No action strictly required.", "line": 87, "start_line": 87, "side": "RIGHT", "start_side": "RIGHT"}]

Posted via Macroscope — Scout Test Review

@KDKHD
Copy link
Copy Markdown
Member Author

KDKHD commented Apr 20, 2026

/flaky scoutConfig:src/platform/plugins/shared/workflows_extensions/test/scout/api/playwright.config.ts:30

@kibanamachine
Copy link
Copy Markdown
Contributor

Flaky Test Runner

✅ Build triggered - kibana-flaky-test-suite-runner#11735

  • src/platform/plugins/shared/workflows_extensions/test/scout/api/playwright.config.ts x30

@kibanamachine
Copy link
Copy Markdown
Contributor

Flaky Test Runner Stats

🎉 All tests passed! - kibana-flaky-test-suite-runner#11735

[✅] src/platform/plugins/shared/workflows_extensions/test/scout/api/playwright.config.ts: 30/30 tests passed.

see run history

KDKHD and others added 4 commits April 21, 2026 09:44
Three constants were dropped during a merge with main:
- SIEM_MIGRATIONS_MANAGE_PATH
- EXCLUDED_GAP_REASONS_KEY
- NEW_FEATURES_TOUR_STORAGE_KEYS.AI_RULE_CREATION_MENU

These are still referenced by other files in the plugin and their
removal caused 17 type check errors in CI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@KDKHD
Copy link
Copy Markdown
Member Author

KDKHD commented Apr 21, 2026

/ci

"serverless",
"agentBuilder",
"llmTasks",
"workflowsManagement",
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 really needed? Everything should be configurable via workflowsExtensions alone.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yep not needed - accidentally carried over from #253245

Comment on lines +818 to +833
if (plugins.workflowsExtensions) {
const workflowsExtensions = plugins.workflowsExtensions;
core
.getStartServices()
.then(async ([coreStart]) => {
await registerWorkflowSteps(workflowsExtensions, coreStart);
})
.catch((error) => {
this.logger.error(
`[RegisterAlertValidationSteps] Error registering alert validation steps: ${error.message}`,
{
error: error.stack,
}
);
});
}
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.

It would be better to call workflowsExtensions.registerStepDefinition synchronously.
The registry already accepts an async loader for the step definition, and we manage the promise internally. This approach delays registration beyond the start() lifecycle, which can be problematic.
However, I see the feature flag is preventing the registration, which is something we do not have a solution for.
I'll create a small PR adding support for it (on the server side as well), and I'll update this logic.
Let's keep this approach for now. I'll keep you posted @KDKHD .

Copy link
Copy Markdown
Contributor

@semd semd Apr 21, 2026

Choose a reason for hiding this comment

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

I just realized this is the server side. The comment is referring to the public side registration.
nvm, I'll adapt both anyway.

Copy link
Copy Markdown
Contributor

@semd semd left a comment

Choose a reason for hiding this comment

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

Approving.
Remember to remove the unnecessary dependency.

LGTM!

@elasticmachine
Copy link
Copy Markdown
Contributor

💛 Build succeeded, but was flaky

Failed CI Steps

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
securitySolution 9255 9267 +12

Async chunks

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

id before after diff
securitySolution 11.7MB 11.7MB +15.0KB

Page load bundle

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

id before after diff
securitySolution 146.4KB 146.7KB +357.0B
Unknown metric groups

async chunk count

id before after diff
securitySolution 98 103 +5

References to deprecated APIs

id before after diff
securitySolution 546 554 +8

Unreferenced deprecated APIs

id before after diff
securitySolution 546 554 +8

History

@KDKHD KDKHD merged commit fc676fa into elastic:main Apr 22, 2026
21 checks passed
mbondyra added a commit to mbondyra/kibana that referenced this pull request Apr 22, 2026
…sationChanges23

* commit '9a7b717c662d1c904052bc59f0e5a81daab87c7f': (145 commits)
  Upgrade EUI to v114.2.0 (elastic#264550)
  [Entity Analytics] Add missing OpenAPI descriptions and examples to p… (elastic#264778)
  [Entity Resolution] Clarify CSV upload result for already-linked entities (elastic#264689)
  [AI Infra] Fix failing GenAI Settings Scout tests (elastic#260496)
  [Agent Builder] [Bug Bash] OAuth connector settings mention fields that are not there (elastic#264756)
  [performance] process-wide cache for advanced settings lookup (elastic#262618)
  [CI] Update limits.yml for securitySolution (elastic#264946)
  [SLO] Fix APM embeddable ids (elastic#264750)
  [EDR Workflows] Unify artifacts empty state buttons (elastic#264389)
  [Alert Triage workflow] Adds security.buildAlertEntityGraph and security.renderAlertNarrative… (elastic#259159)
  [SigEvents] Add KI feature identification endpoints and refactor task to use shared service (elastic#263528)
  [Scout] Migrate Data Views API tests from FTR - Part5 (elastic#264088)
  [Cases] Apply shared extended_fields path util server side (elastic#264706)
  [Lens as code] Fix metric trendline (elastic#264777)
  [api-docs] 2026-04-22 Daily api_docs build (elastic#264882)
  [Scout] Update test config manifests (elastic#264575)
  [workflows_management] Lazy-load Zod connector schemas to cut idle memory (elastic#264283)
  [ES|QL] Fix ES|QL columns reset race during active fetch (elastic#263947)
  [Content List] Column layout props, sticky actions, and title click handlers (elastic#264203)
  [Lens as code] Validate `id` in route for new vis types (elastic#264480)
  ...
semd added a commit that referenced this pull request Apr 22, 2026
## Summary

From: #259159

Enables conditional async registration of workflow custom steps on both
the public and server side of the `workflows_extensions` plugin.

- `registerStepDefinition` now accepts a sync definition **or** an async
loader (`() => Promise<Definition | undefined>`). A loader resolving to
`undefined` is a no-op, so plugins can gate registration behind async
checks (e.g. feature flags, license, capabilities) without an explicit
branch around the call.
- Adds `isReady()` to the shared `WorkflowsExtensionsStartContract`
(already present on the public start; now also on the server start). It
resolves once every pending async loader has settled.
- Loader rejections — and any error thrown while inserting the resolved
definition into the registry — are caught and **logged via the plugin
logger** as `Failed to register step definition` with the original error
attached as meta. They do **not** propagate, so a single broken loader
cannot break other steps or workflow execution as a whole. Consequently,
`isReady()` always resolves; consumers can `await` it without try/catch.
- The execution engine `setupDependencies` awaits
`workflowsExtensions.isReady()` before reading the workflow execution,
so step handlers registered asynchronously are guaranteed to be
available when the engine runs.
- Both `PublicStepRegistry` and `ServerStepRegistry` now take a `Logger`
in their constructor, wired from the corresponding plugin's
`initializerContext.logger.get()`.

## Changes

- `workflows_extensions/common/types.ts` — add `isReady():
Promise<void>` to `WorkflowsExtensionsStartContract`.
- `workflows_extensions/public/step_registry/step_registry.ts` — accept
loader, skip on `undefined`, log loader/registration errors via the
injected `Logger`.
- `workflows_extensions/server/step_registry/step_registry.ts` — same
async/loader behavior + `whenReady()`, takes a `Logger` in the
constructor.
- `workflows_extensions/server/plugin.ts` — expose `isReady()` from
start; accept `ServerStepDefinitionOrLoader` in
`registerStepDefinition`; pass the plugin logger to
`ServerStepRegistry`.
- `workflows_extensions/public/plugin.ts` — pass the plugin logger to
`PublicStepRegistry`.
- `workflows_extensions/public/types.ts` & `server/types.ts` — types for
the new loader signature; move `isReady()` into the shared start
contract.
- `workflows_extensions/server/mocks.ts` — add `isReady` to the start
mock.
- `workflows_extensions/dev_docs/STEPS.md` — document async +
conditional registration on both sides, the log-don't-throw error model,
and the server-side `isReady()`.
-
`workflows_execution_engine/server/execution_functions/setup_dependencies.ts`
— `await workflowsExtensions.isReady()` before fetching the workflow
execution.

## Test plan

- Unit tests updated/added for both registries (sync, async loader,
`undefined`-skip, mixed sync/async, duplicate handling via async loader,
loader rejection — all assert that `whenReady()` resolves and that
`logger.error` is called with the original error).
- Unit tests added for `setupDependencies` covering: it awaits
`isReady()` before reading the execution, and propagates errors thrown
by `isReady()`.
- All affected Jest suites pass locally.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
tiansivive pushed a commit to tiansivive/kibana that referenced this pull request Apr 23, 2026
…264788)

## Summary

From: elastic#259159

Enables conditional async registration of workflow custom steps on both
the public and server side of the `workflows_extensions` plugin.

- `registerStepDefinition` now accepts a sync definition **or** an async
loader (`() => Promise<Definition | undefined>`). A loader resolving to
`undefined` is a no-op, so plugins can gate registration behind async
checks (e.g. feature flags, license, capabilities) without an explicit
branch around the call.
- Adds `isReady()` to the shared `WorkflowsExtensionsStartContract`
(already present on the public start; now also on the server start). It
resolves once every pending async loader has settled.
- Loader rejections — and any error thrown while inserting the resolved
definition into the registry — are caught and **logged via the plugin
logger** as `Failed to register step definition` with the original error
attached as meta. They do **not** propagate, so a single broken loader
cannot break other steps or workflow execution as a whole. Consequently,
`isReady()` always resolves; consumers can `await` it without try/catch.
- The execution engine `setupDependencies` awaits
`workflowsExtensions.isReady()` before reading the workflow execution,
so step handlers registered asynchronously are guaranteed to be
available when the engine runs.
- Both `PublicStepRegistry` and `ServerStepRegistry` now take a `Logger`
in their constructor, wired from the corresponding plugin's
`initializerContext.logger.get()`.

## Changes

- `workflows_extensions/common/types.ts` — add `isReady():
Promise<void>` to `WorkflowsExtensionsStartContract`.
- `workflows_extensions/public/step_registry/step_registry.ts` — accept
loader, skip on `undefined`, log loader/registration errors via the
injected `Logger`.
- `workflows_extensions/server/step_registry/step_registry.ts` — same
async/loader behavior + `whenReady()`, takes a `Logger` in the
constructor.
- `workflows_extensions/server/plugin.ts` — expose `isReady()` from
start; accept `ServerStepDefinitionOrLoader` in
`registerStepDefinition`; pass the plugin logger to
`ServerStepRegistry`.
- `workflows_extensions/public/plugin.ts` — pass the plugin logger to
`PublicStepRegistry`.
- `workflows_extensions/public/types.ts` & `server/types.ts` — types for
the new loader signature; move `isReady()` into the shared start
contract.
- `workflows_extensions/server/mocks.ts` — add `isReady` to the start
mock.
- `workflows_extensions/dev_docs/STEPS.md` — document async +
conditional registration on both sides, the log-don't-throw error model,
and the server-side `isReady()`.
-
`workflows_execution_engine/server/execution_functions/setup_dependencies.ts`
— `await workflowsExtensions.isReady()` before fetching the workflow
execution.

## Test plan

- Unit tests updated/added for both registries (sync, async loader,
`undefined`-skip, mixed sync/async, duplicate handling via async loader,
loader rejection — all assert that `whenReady()` resolves and that
`logger.error` is called with the original error).
- Unit tests added for `setupDependencies` covering: it awaits
`isReady()` before reading the execution, and propagates errors thrown
by `isReady()`.
- All affected Jest suites pass locally.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
KDKHD added a commit that referenced this pull request Apr 23, 2026
…nc loaders (#265230)

## Summary

Follows up on #264788 (merged by @semd) which added
async-loader support to the `ServerStepRegistry` and
`PublicStepRegistry`.

Previously, `registerStepDefinition` was called inside a deferred
`getStartServices().then()` callback — meaning registration happened
*after* the `setup()` lifecycle completed. semd flagged this as
problematic in review comments on #259159 ([comment
1](#259159 (comment)),
[comment
2](#259159 (comment))).

This PR applies the fix on the security_solution side:
`registerStepDefinition` is now called **synchronously** during
`setup()`. Each step is registered with an async loader that checks the
feature flag at resolution time and returns `undefined` to skip
registration when the flag is disabled.

Changes on both server and public sides:
- `registerWorkflowSteps` is now a synchronous function accepting
`CoreSetup` instead of `CoreStart`
- Each step is wrapped in an async loader that defers the feature-flag
check to resolution time
- `plugin.ts` / `plugin.tsx` call `registerWorkflowSteps` directly in
`setup()` (no deferred `.then()`)
- New unit tests for both server and public `registerWorkflowSteps`

## Test plan

- [ ] `node scripts/jest
x-pack/solutions/security/plugins/security_solution/server/workflows/step_types/register_workflow_steps.test.ts`
- [ ] `node scripts/jest
x-pack/solutions/security/plugins/security_solution/public/workflows/step_types/register_workflow_steps.test.ts`
- [ ] Confirm no regression in existing workflow step tests
smith pushed a commit to smith/kibana that referenced this pull request Apr 23, 2026
…nc loaders (elastic#265230)

## Summary

Follows up on elastic#264788 (merged by @semd) which added
async-loader support to the `ServerStepRegistry` and
`PublicStepRegistry`.

Previously, `registerStepDefinition` was called inside a deferred
`getStartServices().then()` callback — meaning registration happened
*after* the `setup()` lifecycle completed. semd flagged this as
problematic in review comments on elastic#259159 ([comment
1](elastic#259159 (comment)),
[comment
2](elastic#259159 (comment))).

This PR applies the fix on the security_solution side:
`registerStepDefinition` is now called **synchronously** during
`setup()`. Each step is registered with an async loader that checks the
feature flag at resolution time and returns `undefined` to skip
registration when the flag is disabled.

Changes on both server and public sides:
- `registerWorkflowSteps` is now a synchronous function accepting
`CoreSetup` instead of `CoreStart`
- Each step is wrapped in an async loader that defers the feature-flag
check to resolution time
- `plugin.ts` / `plugin.tsx` call `registerWorkflowSteps` directly in
`setup()` (no deferred `.then()`)
- New unit tests for both server and public `registerWorkflowSteps`

## Test plan

- [ ] `node scripts/jest
x-pack/solutions/security/plugins/security_solution/server/workflows/step_types/register_workflow_steps.test.ts`
- [ ] `node scripts/jest
x-pack/solutions/security/plugins/security_solution/public/workflows/step_types/register_workflow_steps.test.ts`
- [ ] Confirm no regression in existing workflow step tests
rbrtj pushed a commit to walterra/kibana that referenced this pull request Apr 27, 2026
…nc loaders (elastic#265230)

## Summary

Follows up on elastic#264788 (merged by @semd) which added
async-loader support to the `ServerStepRegistry` and
`PublicStepRegistry`.

Previously, `registerStepDefinition` was called inside a deferred
`getStartServices().then()` callback — meaning registration happened
*after* the `setup()` lifecycle completed. semd flagged this as
problematic in review comments on elastic#259159 ([comment
1](elastic#259159 (comment)),
[comment
2](elastic#259159 (comment))).

This PR applies the fix on the security_solution side:
`registerStepDefinition` is now called **synchronously** during
`setup()`. Each step is registered with an async loader that checks the
feature flag at resolution time and returns `undefined` to skip
registration when the flag is disabled.

Changes on both server and public sides:
- `registerWorkflowSteps` is now a synchronous function accepting
`CoreSetup` instead of `CoreStart`
- Each step is wrapped in an async loader that defers the feature-flag
check to resolution time
- `plugin.ts` / `plugin.tsx` call `registerWorkflowSteps` directly in
`setup()` (no deferred `.then()`)
- New unit tests for both server and public `registerWorkflowSteps`

## Test plan

- [ ] `node scripts/jest
x-pack/solutions/security/plugins/security_solution/server/workflows/step_types/register_workflow_steps.test.ts`
- [ ] `node scripts/jest
x-pack/solutions/security/plugins/security_solution/public/workflows/step_types/register_workflow_steps.test.ts`
- [ ] Confirm no regression in existing workflow step tests
SoniaSanzV pushed a commit to SoniaSanzV/kibana that referenced this pull request Apr 27, 2026
…ity.renderAlertNarrative… (elastic#259159)

… steps

## Summary

Migrates two new workflow step definitions from
`feature/alert-false-positive-queue` into this branch so they can be
developed and shipped independently.

The two steps added are:
- **`renderAlertNarrativeStepDefinition`** — renders a human-readable
narrative for an alert based on its event category (process, network,
file, DNS, authentication, cloud, registry, ML, threat match)
- **`buildAlertEntityGraphStepDefinition`** — builds an entity
relationship graph for an alert by querying related events and scoring
entity connections

Both steps are registered behind the feature flag
`securitySolution.registerAlertValidationStepsEnabled` (defaults to
`true`) to allow safe removal of the flag at a later date without a code
change. These 2 steps will be used by the alert false positive workflow
in
[feature/alert-false-positive-queue](https://github.com/KDKHD/kibana/tree/feature/alert-false-positive-queue)

## Changes

- `kibana.jsonc` — adds `workflowsManagement` and `workflowsExtensions`
as optional plugin dependencies
- `server/plugin_contract.ts` / `public/types.ts` — adds
`WorkflowsExtensions` types to setup/start dependency interfaces
- `common/constants.ts` — adds
`REGISTER_ALERT_VALIDATION_STEPS_FEATURE_FLAG` and
`PREINSTALLED_WORKFLOWS_FEATURE_FLAG` constants
- `server/plugin.ts` / `public/plugin.tsx` — registers step definitions
on plugin setup, gated by the feature flag
- `server/workflows/step_types/render_alert_narrative_step/` —
server-side step implementation with strategy pattern per event category
- `server/workflows/step_types/build_alert_entity_graph_step/` —
server-side step implementation with entity graph traversal and scoring
- `public/workflows/step_types/render_alert_narrative_step/` —
client-side step definition
- `public/workflows/step_types/build_alert_entity_graph_step/` —
client-side step definition

## Follow-up

Remove the `REGISTER_ALERT_VALIDATION_STEPS_FEATURE_FLAG` guard in
`server/workflows/step_types/register_workflow_steps.ts` and
`public/workflows/step_types/register_workflow_steps.ts` once the steps
are ready to ship unconditionally.


### Checklist

Check the PR satisfies following conditions. 

Reviewers should verify this PR satisfies this list as well.

- [X] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [X]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [X] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [X] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [X] This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.
- [X] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [X] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
- [X] Review the [backport
guidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing)
and apply applicable `backport:*` labels.

### Identify risks

Does this PR introduce any risks? For example, consider risks like hard
to test bugs, performance regression, potential of data loss.

Describe the risk, its severity, and mitigation for each identified
risk. Invite stakeholders and evaluate how to proceed before merging.

- [ ] [See some risk
examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)
- [ ] ...

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
SoniaSanzV pushed a commit to SoniaSanzV/kibana that referenced this pull request Apr 27, 2026
…264788)

## Summary

From: elastic#259159

Enables conditional async registration of workflow custom steps on both
the public and server side of the `workflows_extensions` plugin.

- `registerStepDefinition` now accepts a sync definition **or** an async
loader (`() => Promise<Definition | undefined>`). A loader resolving to
`undefined` is a no-op, so plugins can gate registration behind async
checks (e.g. feature flags, license, capabilities) without an explicit
branch around the call.
- Adds `isReady()` to the shared `WorkflowsExtensionsStartContract`
(already present on the public start; now also on the server start). It
resolves once every pending async loader has settled.
- Loader rejections — and any error thrown while inserting the resolved
definition into the registry — are caught and **logged via the plugin
logger** as `Failed to register step definition` with the original error
attached as meta. They do **not** propagate, so a single broken loader
cannot break other steps or workflow execution as a whole. Consequently,
`isReady()` always resolves; consumers can `await` it without try/catch.
- The execution engine `setupDependencies` awaits
`workflowsExtensions.isReady()` before reading the workflow execution,
so step handlers registered asynchronously are guaranteed to be
available when the engine runs.
- Both `PublicStepRegistry` and `ServerStepRegistry` now take a `Logger`
in their constructor, wired from the corresponding plugin's
`initializerContext.logger.get()`.

## Changes

- `workflows_extensions/common/types.ts` — add `isReady():
Promise<void>` to `WorkflowsExtensionsStartContract`.
- `workflows_extensions/public/step_registry/step_registry.ts` — accept
loader, skip on `undefined`, log loader/registration errors via the
injected `Logger`.
- `workflows_extensions/server/step_registry/step_registry.ts` — same
async/loader behavior + `whenReady()`, takes a `Logger` in the
constructor.
- `workflows_extensions/server/plugin.ts` — expose `isReady()` from
start; accept `ServerStepDefinitionOrLoader` in
`registerStepDefinition`; pass the plugin logger to
`ServerStepRegistry`.
- `workflows_extensions/public/plugin.ts` — pass the plugin logger to
`PublicStepRegistry`.
- `workflows_extensions/public/types.ts` & `server/types.ts` — types for
the new loader signature; move `isReady()` into the shared start
contract.
- `workflows_extensions/server/mocks.ts` — add `isReady` to the start
mock.
- `workflows_extensions/dev_docs/STEPS.md` — document async +
conditional registration on both sides, the log-don't-throw error model,
and the server-side `isReady()`.
-
`workflows_execution_engine/server/execution_functions/setup_dependencies.ts`
— `await workflowsExtensions.isReady()` before fetching the workflow
execution.

## Test plan

- Unit tests updated/added for both registries (sync, async loader,
`undefined`-skip, mixed sync/async, duplicate handling via async loader,
loader rejection — all assert that `whenReady()` resolves and that
`logger.error` is called with the original error).
- Unit tests added for `setupDependencies` covering: it awaits
`isReady()` before reading the execution, and propagates errors thrown
by `isReady()`.
- All affected Jest suites pass locally.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
SoniaSanzV pushed a commit to SoniaSanzV/kibana that referenced this pull request Apr 27, 2026
…nc loaders (elastic#265230)

## Summary

Follows up on elastic#264788 (merged by @semd) which added
async-loader support to the `ServerStepRegistry` and
`PublicStepRegistry`.

Previously, `registerStepDefinition` was called inside a deferred
`getStartServices().then()` callback — meaning registration happened
*after* the `setup()` lifecycle completed. semd flagged this as
problematic in review comments on elastic#259159 ([comment
1](elastic#259159 (comment)),
[comment
2](elastic#259159 (comment))).

This PR applies the fix on the security_solution side:
`registerStepDefinition` is now called **synchronously** during
`setup()`. Each step is registered with an async loader that checks the
feature flag at resolution time and returns `undefined` to skip
registration when the flag is disabled.

Changes on both server and public sides:
- `registerWorkflowSteps` is now a synchronous function accepting
`CoreSetup` instead of `CoreStart`
- Each step is wrapped in an async loader that defers the feature-flag
check to resolution time
- `plugin.ts` / `plugin.tsx` call `registerWorkflowSteps` directly in
`setup()` (no deferred `.then()`)
- New unit tests for both server and public `registerWorkflowSteps`

## Test plan

- [ ] `node scripts/jest
x-pack/solutions/security/plugins/security_solution/server/workflows/step_types/register_workflow_steps.test.ts`
- [ ] `node scripts/jest
x-pack/solutions/security/plugins/security_solution/public/workflows/step_types/register_workflow_steps.test.ts`
- [ ] Confirm no regression in existing workflow step tests
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.5.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants