Skip to content

[One Workflow] Support triggering workflows for recovered and ongoing alerts#256289

Closed
talboren wants to merge 8 commits intoelastic:mainfrom
talboren:feature/alert-states-workflow
Closed

[One Workflow] Support triggering workflows for recovered and ongoing alerts#256289
talboren wants to merge 8 commits intoelastic:mainfrom
talboren:feature/alert-states-workflow

Conversation

@talboren
Copy link
Copy Markdown
Contributor

@talboren talboren commented Mar 5, 2026

Summary

  • Adds an alertStates configuration ({ new, ongoing, recovered }) to the workflow connector, allowing users to select which alert states should trigger workflow execution
  • Renders a "Run workflow for" checkbox group (Firing / Ongoing / Recovered) in the rule action UI, between the workflow selector and the action frequency switch
  • Defaults to { new: true, ongoing: false, recovered: false } — exactly matching current behavior so existing rules require zero migration

References

Closes elastic/security-team#16239

Changes

Layer File Change
Server types server/connectors/workflows/types.ts Added AlertStates interface and alertStates? to RunWorkflowParams
Server schema server/connectors/workflows/schema.ts Added alertStates to Zod and config-schema (all optional)
Server adapter server/connectors/workflows/index.ts Filters alerts by state before building event; forwards alertStates
Shared utility common/utils/build_alert_event.ts Merges new, ongoing, recovered alert arrays
Public types public/connectors/workflows/types.ts Added AlertStates and alertStates? to WorkflowsActionParams
Public UI public/connectors/workflows/workflows_params.tsx Added "Run workflow for" checkbox group

YAML

name: Print Alert Status
description: Logs the status of each alert received by the workflow
triggers:
  - type: alert
steps:
  - name: print_alert_status
    type: console
    with:
      message: |
        {% for alert in event.alerts %}
        Alert ID: {{ alert._id }}
        Status: {{ alert._source['kibana.alert.status'] }}
        Rule: {{ event.rule.name }}
        ---
        {% endfor %}
CleanShot 2026-03-09 at 12 25 35@2x CleanShot 2026-03-09 at 12 25 16@2x

Made with Cursor

talboren added 2 commits March 5, 2026 17:39
Add alertStates configuration to the workflow connector, allowing users
to select which alert states (firing, ongoing, recovered) should trigger
workflow execution. Defaults to firing-only for full backward compat
with existing rules -- no migration needed.

Closes elastic/security-team#16239

Made-with: Cursor
@talboren talboren requested a review from a team as a code owner March 5, 2026 16:23
@talboren talboren 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) labels Mar 5, 2026
talboren added 2 commits March 8, 2026 14:17
- Spread original alerts into filteredAlerts to preserve `all` property
- Resolve alertStates to concrete booleans to match Zod-inferred types
- Update connector_types.test.ts.snap for new alertStates schema

Made-with: Cursor
@talboren talboren requested a review from a team as a code owner March 8, 2026 12:47
@talboren talboren requested a review from Copilot March 9, 2026 10:21
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds an alertStates configuration to the Workflows connector so users can choose which alert states (Firing/New, Ongoing, Recovered) trigger workflow execution, while keeping the default behavior unchanged for existing rules.

Changes:

  • Adds alertStates to server/public types + server validation schemas.
  • Filters alert groups by selected states before building the workflow alert event, and merges selected states into event.alerts.
  • Adds a “Run workflow for” checkbox group in the rule action UI + updates/extends test coverage and snapshots.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
x-pack/platform/plugins/shared/actions/server/integration_tests/snapshots/connector_types.test.ts.snap Updates connector schema snapshot to include alertStates.
src/platform/plugins/shared/workflows_management/server/connectors/workflows/types.ts Introduces server-side AlertStates type and wires it into params.
src/platform/plugins/shared/workflows_management/server/connectors/workflows/schema.ts Adds Zod + config-schema validation for alertStates.
src/platform/plugins/shared/workflows_management/server/connectors/workflows/index.ts Resolves defaults + filters alert groups by selected states before building the event.
src/platform/plugins/shared/workflows_management/server/connectors/workflows/index.test.ts Adds adapter tests for defaulting and inclusion/exclusion by alertStates.
src/platform/plugins/shared/workflows_management/public/connectors/workflows/workflows_params.tsx Adds UI checkbox group and initializes alertStates defaults.
src/platform/plugins/shared/workflows_management/public/connectors/workflows/workflows_params.test.tsx Adds UI tests for rendering, defaults, toggling, and initialization.
src/platform/plugins/shared/workflows_management/public/connectors/workflows/types.ts Exposes AlertStates + adds it to public action params.
src/platform/plugins/shared/workflows_management/common/utils/build_alert_event.ts Merges new/ongoing/recovered alert arrays into event.alerts.
src/platform/plugins/shared/workflows_management/common/utils/build_alert_event.test.ts Adds unit tests for alert merging and rule metadata.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +107 to +123
if (actionParams.subActionParams.summaryMode === undefined) {
editAction(
'subActionParams',
{ ...actionParams.subActionParams, summaryMode: true },
index
);
}
if (!actionParams.subActionParams.alertStates) {
editAction(
'subActionParams',
{
...actionParams.subActionParams,
alertStates: { new: true, ongoing: false, recovered: false },
},
index
);
}
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

The useEffect can call editAction('subActionParams', ...) twice in the same pass when both summaryMode is undefined and alertStates is missing. The second call spreads the original actionParams.subActionParams (which may still have summaryMode: undefined), potentially overwriting the first update and leaving summaryMode unset. Combine these defaults into a single computed nextSubActionParams object (setting both summaryMode and alertStates when needed) and call editAction once (or only when the computed object differs).

Suggested change
if (actionParams.subActionParams.summaryMode === undefined) {
editAction(
'subActionParams',
{ ...actionParams.subActionParams, summaryMode: true },
index
);
}
if (!actionParams.subActionParams.alertStates) {
editAction(
'subActionParams',
{
...actionParams.subActionParams,
alertStates: { new: true, ongoing: false, recovered: false },
},
index
);
}
let nextSubActionParams = actionParams.subActionParams;
let needsUpdate = false;
if (nextSubActionParams.summaryMode === undefined) {
nextSubActionParams = {
...nextSubActionParams,
summaryMode: true,
};
needsUpdate = true;
}
if (!nextSubActionParams.alertStates) {
nextSubActionParams = {
...nextSubActionParams,
alertStates: { new: true, ongoing: false, recovered: false },
};
needsUpdate = true;
}
if (needsUpdate) {
editAction('subActionParams', nextSubActionParams, index);
}

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +19
export interface AlertStates {
[key: string]: boolean | undefined;
new?: boolean;
ongoing?: boolean;
recovered?: boolean;
}
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

The index signature ([key: string]: ...) makes AlertStates accept arbitrary keys, which weakens type-safety (e.g., typos like { recoevered: true } compile) and diverges from the server’s fixed-key shape. Consider removing the index signature and using explicit keys only (optionally paired with a type AlertStateId = 'new' | 'ongoing' | 'recovered' for the checkbox option IDs) to keep public/server contracts aligned and prevent silent misconfiguration.

Copilot uses AI. Check for mistakes.
Comment on lines +13 to +17
const AlertStatesSchema = z.object({
new: z.boolean().optional().default(true),
ongoing: z.boolean().optional().default(false),
recovered: z.boolean().optional().default(false),
});
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

AlertStatesSchema is not strict, so unknown keys can be silently stripped/accepted by Zod parsing (depending on how parsing is performed), which can hide client typos and may differ from the stricter config-schema expectations. Consider making this schema strict (e.g., .strict()) so invalid keys are rejected consistently at validation time.

Suggested change
const AlertStatesSchema = z.object({
new: z.boolean().optional().default(true),
ongoing: z.boolean().optional().default(false),
recovered: z.boolean().optional().default(false),
});
const AlertStatesSchema = z
.object({
new: z.boolean().optional().default(true),
ongoing: z.boolean().optional().default(false),
recovered: z.boolean().optional().default(false),
})
.strict();

Copilot uses AI. Check for mistakes.
inputs: z.any().optional(),
spaceId: z.string(),
summaryMode: z.boolean().optional().default(true),
alertStates: AlertStatesSchema.optional(),
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

AlertStatesSchema is not strict, so unknown keys can be silently stripped/accepted by Zod parsing (depending on how parsing is performed), which can hide client typos and may differ from the stricter config-schema expectations. Consider making this schema strict (e.g., .strict()) so invalid keys are rejected consistently at validation time.

Copilot uses AI. Check for mistakes.
Comment on lines 175 to +180
const { workflowId, summaryMode = true } = subActionParams;
const resolvedAlertStates = {
new: subActionParams.alertStates?.new !== false,
ongoing: subActionParams.alertStates?.ongoing === true,
recovered: subActionParams.alertStates?.recovered === true,
};
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

The logic to resolve defaults for alertStates is duplicated in both the try and catch paths. Extracting this into a small helper (e.g., resolveAlertStates(alertStates?: AlertStates)) would reduce repetition and keep server-side defaulting semantics consistent if they change later.

Copilot uses AI. Check for mistakes.
Comment on lines +223 to +229
alertStates: params?.subActionParams?.alertStates
? {
new: params.subActionParams.alertStates.new !== false,
ongoing: params.subActionParams.alertStates.ongoing === true,
recovered: params.subActionParams.alertStates.recovered === true,
}
: undefined,
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

The logic to resolve defaults for alertStates is duplicated in both the try and catch paths. Extracting this into a small helper (e.g., resolveAlertStates(alertStates?: AlertStates)) would reduce repetition and keep server-side defaulting semantics consistent if they change later.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@VladimirFilonov VladimirFilonov left a comment

Choose a reason for hiding this comment

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

LGTM

@elasticmachine
Copy link
Copy Markdown
Contributor

⏳ Build in-progress, with failures

Failed CI Steps

Test Failures

  • [job] [logs] Scout: [ security / entity_store ] plugin / local-stateful-classic - Entity Store CRUD API tests - Should perform a bulk upsert
  • [job] [logs] Scout: [ security / entity_store ] plugin / local-stateful-classic - Entity Store History Snapshot - history snapshot: copies latest to history index and resets behaviors on latest

History

@pmuellr
Copy link
Copy Markdown
Contributor

pmuellr commented Mar 11, 2026

We've not hooked up our "add a comment about intermediate releases on connector parameter changes", so here it is manually:

It looks like you're updating the parameters for a connector type!

Please review the guidelines for making additive changes to connector type parameters and determine if your changes require an intermediate release.

In practice this means two PRs - one that introduces the schema changes, but adds no code (or minimal code) that sets a value in the new schema fields. After that has been merged and is running in serverless, the second PR setting the field can be merged.

@pmuellr
Copy link
Copy Markdown
Contributor

pmuellr commented Mar 11, 2026

@nastasha-solomon I noticed the copy in the dialog says "Firing alerts", figured I'd ping you to see if that's the current terminology. I thought we used "active" in the past, though "firing" is probably conceptually better :-)

@jcger jcger self-requested a review March 11, 2026 13:37
@talboren talboren closed this Mar 12, 2026
talboren added a commit to talboren/kibana that referenced this pull request Mar 12, 2026
Add backend-only support for configuring which alert states (new,
ongoing, recovered) trigger workflow execution. This is the first
part of an intermediate release strategy — schema and adapter changes
land first, UI follows in a subsequent PR.

- Add AlertStates interface and optional alertStates to types/schema
- Add resolveAlertStates helper with backward-compatible defaults
  (new: true, ongoing: false, recovered: false)
- Filter alert groups by resolved states in buildActionParams
- Merge new/ongoing/recovered alert arrays into flat event.alerts
- Schema uses optional booleans with no defaults (safe for rollback)

Supersedes elastic#256289 (closed) which included both backend and UI changes.

Closes elastic/security-team#16239

Made-with: Cursor
talboren added a commit that referenced this pull request Mar 18, 2026
…#257363)

## Summary

Adds backend-only support for configuring which alert states (`new`,
`ongoing`, `recovered`) trigger workflow execution. This is the **first
part of an intermediate release strategy** — schema and adapter changes
land first, with the UI to follow in a subsequent PR.

- Adds `AlertStates` interface and optional `alertStates` field to the
workflows connector types and schema (Zod + config-schema)
- Adds `resolveAlertStates()` helper with backward-compatible defaults
(`new: true, ongoing: false, recovered: false`) — existing rules
continue to work without migration
- Filters alert groups by resolved states in `buildActionParams` before
building the alert event
- Updates `buildAlertEvent` to merge `new`/`ongoing`/`recovered` alert
arrays into a flat `event.alerts` array (preserves Liquid template
compatibility)
- Schema fields are optional with no defaults, ensuring safe rollbacks
during serverless rolling upgrades

**Why backend-only?** Per the intermediate release pattern for
serverless, schema changes must land and be deployed before the UI that
writes those fields. This ensures older nodes can validate objects
during rolling upgrades and rollbacks.

Supersedes #256289 (closed), which
included both backend and UI changes. The UI portion (alert state
checkbox group in the rule action form) will follow in a separate PR.

### PR review feedback addressed from #256289:
- Removed index signature from `AlertStates` interface for stricter type
safety
- Made `AlertStatesSchema` strict (`.strict()`) to reject unknown keys
- Extracted `resolveAlertStates()` helper to avoid duplicated default
logic

## References

Closes elastic/security-team#16239


Made with [Cursor](https://cursor.com)
qn895 pushed a commit to qn895/kibana that referenced this pull request Mar 18, 2026
…elastic#257363)

## Summary

Adds backend-only support for configuring which alert states (`new`,
`ongoing`, `recovered`) trigger workflow execution. This is the **first
part of an intermediate release strategy** — schema and adapter changes
land first, with the UI to follow in a subsequent PR.

- Adds `AlertStates` interface and optional `alertStates` field to the
workflows connector types and schema (Zod + config-schema)
- Adds `resolveAlertStates()` helper with backward-compatible defaults
(`new: true, ongoing: false, recovered: false`) — existing rules
continue to work without migration
- Filters alert groups by resolved states in `buildActionParams` before
building the alert event
- Updates `buildAlertEvent` to merge `new`/`ongoing`/`recovered` alert
arrays into a flat `event.alerts` array (preserves Liquid template
compatibility)
- Schema fields are optional with no defaults, ensuring safe rollbacks
during serverless rolling upgrades

**Why backend-only?** Per the intermediate release pattern for
serverless, schema changes must land and be deployed before the UI that
writes those fields. This ensures older nodes can validate objects
during rolling upgrades and rollbacks.

Supersedes elastic#256289 (closed), which
included both backend and UI changes. The UI portion (alert state
checkbox group in the rule action form) will follow in a separate PR.

### PR review feedback addressed from elastic#256289:
- Removed index signature from `AlertStates` interface for stricter type
safety
- Made `AlertStatesSchema` strict (`.strict()`) to reject unknown keys
- Extracted `resolveAlertStates()` helper to avoid duplicated default
logic

## References

Closes elastic/security-team#16239


Made with [Cursor](https://cursor.com)
jeramysoucy pushed a commit to jeramysoucy/kibana that referenced this pull request Mar 26, 2026
…elastic#257363)

## Summary

Adds backend-only support for configuring which alert states (`new`,
`ongoing`, `recovered`) trigger workflow execution. This is the **first
part of an intermediate release strategy** — schema and adapter changes
land first, with the UI to follow in a subsequent PR.

- Adds `AlertStates` interface and optional `alertStates` field to the
workflows connector types and schema (Zod + config-schema)
- Adds `resolveAlertStates()` helper with backward-compatible defaults
(`new: true, ongoing: false, recovered: false`) — existing rules
continue to work without migration
- Filters alert groups by resolved states in `buildActionParams` before
building the alert event
- Updates `buildAlertEvent` to merge `new`/`ongoing`/`recovered` alert
arrays into a flat `event.alerts` array (preserves Liquid template
compatibility)
- Schema fields are optional with no defaults, ensuring safe rollbacks
during serverless rolling upgrades

**Why backend-only?** Per the intermediate release pattern for
serverless, schema changes must land and be deployed before the UI that
writes those fields. This ensures older nodes can validate objects
during rolling upgrades and rollbacks.

Supersedes elastic#256289 (closed), which
included both backend and UI changes. The UI portion (alert state
checkbox group in the rule action form) will follow in a separate PR.

### PR review feedback addressed from elastic#256289:
- Removed index signature from `AlertStates` interface for stricter type
safety
- Made `AlertStatesSchema` strict (`.strict()`) to reject unknown keys
- Extracted `resolveAlertStates()` helper to avoid duplicated default
logic

## References

Closes elastic/security-team#16239


Made with [Cursor](https://cursor.com)
talboren added a commit to talboren/kibana that referenced this pull request Mar 26, 2026
Add the UI portion of the alertStates feature — a "Run workflow for"
checkbox group (New / Ongoing / Recovered alerts) in the rule action
form, between the workflow selector and the action frequency switch.

This is the second part of the intermediate release for elastic#257363:
- Part 1 (merged): backend schema + adapter logic (elastic#257363)
- Part 2 (this PR): UI to set alertStates on rule actions

- Add AlertStates type and alertStates? to public WorkflowsActionParams
- Render EuiCheckboxGroup with New/Ongoing/Recovered options
- Use single editAction call in useEffect for initialization
  (addresses Copilot review feedback from elastic#256289)
- Use "New alerts" terminology (not "Firing") per review feedback
- Add 6 new tests for checkbox rendering, defaults, and toggling

Closes elastic/security-team#16239

Made-with: Cursor
talboren added a commit that referenced this pull request Apr 14, 2026
…59770)

## Summary

Adds a "Run workflow for" checkbox group (New / Ongoing / Recovered
alerts) to the workflow connector rule action form, allowing users to
configure which alert states trigger workflow execution.

This is the **second part of the intermediate release** for alertStates
support:
- **Part 1 (merged):** Backend schema + adapter logic — #257363
- **Part 2 (this PR):** UI to set `alertStates` on rule actions

### Changes

- Adds `AlertStates` type and optional `alertStates` to public
`WorkflowsActionParams`
- Renders `EuiCheckboxGroup` with **New alerts** / **Ongoing alerts** /
**Recovered alerts** options between the workflow selector and the
action frequency switch
- Uses a single `editAction` call in `useEffect` for initializing both
`summaryMode` and `alertStates` defaults (addresses [Copilot review
feedback](#256289 (comment))
from #256289)
- Defaults to `{ new: true, ongoing: false, recovered: false }` —
existing rules continue to work without migration
- Uses "New alerts" terminology (not "Firing") per [review
feedback](#256289 (comment))
from @pmuellr

### Background

The original PR #256289 included both backend and UI changes but was
closed to follow the [intermediate release
pattern](https://docs.elastic.dev/reops/developer-guide/best-practices-rules#upgrades-and-rollbacks)
for serverless. The backend changes landed first in #257363, and this PR
completes the feature by enabling the UI.

## References

Closes elastic/security-team#16239


Made with [Cursor](https://cursor.com)

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
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)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants