Repository: elastic/kibana
Pull request #217696: [AI4DSOC] Alert summary alert actions in table and flyout
Author: login: PhilippeOberti
Labels: name: release_note:skip
description: Skip the PR/issue when compiling release notes
name: backport:skip
description: This PR does not require backporting
name: Team:Threat Hunting:Investigations
description: Security Solution Threat Hunting Investigations Team
name: Team:Security Generative AI
description: Security Generative AI
name: v9.1.0
name: v8.19.0
Created: 2025-04-09T14:44:58Z | Merged: 2025-04-14T19:42:30Z

## Summary

This PR adds some alert actions to the AI for SOC alert summary page:
- table row action via a more actions icon button, to allow users to add the alert to a new case, an existing case, or to apply tags to the current alert
- a take action in the footer of the flyout, to allow the user to perform the same actions

Table row actions:

https://github.com/user-attachments/assets/a5991ec0-a1c1-4c8f-821a-5adedd3d68a7

Flyout footer actions:

https://github.com/user-attachments/assets/f5d853d3-8b5e-47f8-ba30-33cdf440651b

### Notes

The code is extremely similar between the 2 components added in this PR. The difference between the 2 is the type of button that is used to open the popover.
I debated 2 others approaches, but was not happy with either:
- create a hook that would return the items and panels for cases and tags, then use that hook to limit the amount of duplicated code in both components. I decided against this as I hate having hooks that return components (in this case `EuiContextMenuItems`...
- create a shared component that would do the logic and have some props to conditionally decide how the button is being displayed. Here also, I decided against this approach because I feel like components that allow these sort of UI customization quickly end up hard to maintain, because we want to change the text, then the color of the button, then the type of icon...

If you feel strongly about the choice I made here, let me know and I'll reconsider the approach! 😄 

## How to test

This needs to be ran in Serverless:
- `yarn es serverless --projectType security`
- `yarn serverless-security --no-base-path`

You also need to enable the AI for SOC tier, by adding the following to your `serverless.security.dev.yaml` file:
```
xpack.securitySolutionServerless.productTypes:
  [
    { product_line: 'ai_soc', product_tier: 'search_ai_lake' },
  ]
```

Use one of these Serverless users:
- `platform_engineer`
- `endpoint_operations_analyst`
- `endpoint_policy_manager`
- `admin`
- `system_indices_superuser`

Then:
- generate data: `yarn test:generate:serverless-dev`
- create 4 catch all rules, each with a name of a AI for SOC integration (`google_secops`, `microsoft_sentinel`,, `sentinel_one` and `crowdstrike`) => to do that you'll need to temporary comment the `serverless.security.dev.yaml` config changes as the rules page is not accessible in AI for SOC.
-  change [this line](https://github.com/elastic/kibana/blob/main/x-pack/solutions/security/plugins/security_solution/public/detections/hooks/alert_summary/use_fetch_integrations.ts#L73) to `installedPackages: availablePackages` to force having some packages installed
- change [this line](https://github.com/elastic/kibana/blob/main/x-pack/solutions/security/plugins/security_solution/public/detections/hooks/alert_summary/use_integrations.ts#L63) to `r.name === p.name` to make sure there will be matches between integrations and rules

### Checklist

- [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] [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

https://github.com/elastic/security-team/issues/11973


Diff:
diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/actions_cell.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/actions_cell.test.tsx
index f7ff7a2612c5f..3dac7381cb395 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/actions_cell.test.tsx
+++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/actions_cell.test.tsx
@@ -8,51 +8,43 @@
 import React from 'react';
 import { render } from '@testing-library/react';
 import type { Alert } from '@kbn/alerting-types';
-import { ActionsCell, ROW_ACTION_FLYOUT_ICON_TEST_ID } from './actions_cell';
+import { ActionsCell } from './actions_cell';
 import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
-import { IOCPanelKey } from '../../../../flyout/ai_for_soc/constants/panel_keys';
+import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs';
+import { MORE_ACTIONS_BUTTON_TEST_ID } from './more_actions_row_control_column';
+import { useAddToCaseActions } from '../../alerts_table/timeline_actions/use_add_to_case_actions';
+import { useAlertTagsActions } from '../../alerts_table/timeline_actions/use_alert_tags_actions';
+import { ROW_ACTION_FLYOUT_ICON_TEST_ID } from './open_flyout_row_control_column';
 
 jest.mock('@kbn/expandable-flyout');
+jest.mock('../../alerts_table/timeline_actions/use_add_to_case_actions');
+jest.mock('../../alerts_table/timeline_actions/use_alert_tags_actions');
 
 describe('ActionsCell', () => {
   it('should render icons', () => {
     (useExpandableFlyoutApi as jest.Mock).mockReturnValue({
       openFlyout: jest.fn(),
     });
+    (useAddToCaseActions as jest.Mock).mockReturnValue({
+      addToCaseActionItems: [],
+    });
+    (useAlertTagsActions as jest.Mock).mockReturnValue({
+      alertTagsItems: [],
+      alertTagsPanels: [],
+    });
 
     const alert: Alert = {
       _id: '_id',
       _index: '_index',
     };
-
-    const { getByTestId } = render(<ActionsCell alert={alert} />);
-
-    expect(getByTestId(ROW_ACTION_FLYOUT_ICON_TEST_ID)).toBeInTheDocument();
-  });
-
-  it('should open flyout after click', () => {
-    const openFlyout = jest.fn();
-    (useExpandableFlyoutApi as jest.Mock).mockReturnValue({
-      openFlyout,
-    });
-
-    const alert: Alert = {
+    const ecsAlert: Ecs = {
       _id: '_id',
       _index: '_index',
     };
 
-    const { getByTestId } = render(<ActionsCell alert={alert} />);
+    const { getByTestId } = render(<ActionsCell alert={alert} ecsAlert={ecsAlert} />);
 
-    getByTestId(ROW_ACTION_FLYOUT_ICON_TEST_ID).click();
-
-    expect(openFlyout).toHaveBeenCalledWith({
-      right: {
-        id: IOCPanelKey,
-        params: {
-          id: alert._id,
-          indexName: alert._index,
-        },
-      },
-    });
+    expect(getByTestId(ROW_ACTION_FLYOUT_ICON_TEST_ID)).toBeInTheDocument();
+    expect(getByTestId(MORE_ACTIONS_BUTTON_TEST_ID)).toBeInTheDocument();
   });
 });
diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/actions_cell.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/actions_cell.tsx
index 61cf6a8cd1edd..0d4612b722a23 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/actions_cell.tsx
+++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/actions_cell.tsx
@@ -5,20 +5,22 @@
  * 2.0.
  */
 
-import React, { memo, useCallback } from 'react';
-import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
-import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+import React, { memo } from 'react';
+import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
 import type { Alert } from '@kbn/alerting-types';
-import { i18n } from '@kbn/i18n';
-import { IOCPanelKey } from '../../../../flyout/ai_for_soc/constants/panel_keys';
-
-export const ROW_ACTION_FLYOUT_ICON_TEST_ID = 'alert-summary-table-row-action-flyout-icon';
+import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs';
+import { OpenFlyoutRowControlColumn } from './open_flyout_row_control_column';
+import { MoreActionsRowControlColumn } from './more_actions_row_control_column';
 
 export interface ActionsCellProps {
   /**
    * Alert data passed from the renderCellValue callback via the AlertWithLegacyFormats interface
    */
   alert: Alert;
+  /**
+   * The Ycs type is @deprecated but needed for the case actions within the more action dropdown
+   */
+  ecsAlert: Ecs;
 }
 
 /**
@@ -29,38 +31,15 @@ export interface ActionsCellProps {
  * - assistant (soon)
  * - more actions (soon)
  */
-export const ActionsCell = memo(({ alert }: ActionsCellProps) => {
-  const { openFlyout } = useExpandableFlyoutApi();
-  const onOpenFlyout = useCallback(
-    () =>
-      openFlyout({
-        right: {
-          id: IOCPanelKey,
-          params: {
-            id: alert._id,
-            indexName: alert._index,
-          },
-        },
-      }),
-    [alert, openFlyout]
-  );
-
-  return (
-    <EuiFlexGroup alignItems="center" gutterSize="xs">
-      <EuiFlexItem>
-        <EuiButtonIcon
-          aria-label={i18n.translate('xpack.securitySolution.alertSummary.table.flyoutIcon', {
-            defaultMessage: 'Open flyout',
-          })}
-          color="primary"
-          data-test-subj={ROW_ACTION_FLYOUT_ICON_TEST_ID}
-          iconType="expand"
-          onClick={onOpenFlyout}
-          size="xs"
-        />
-      </EuiFlexItem>
-    </EuiFlexGroup>
-  );
-});
+export const ActionsCell = memo(({ alert, ecsAlert }: ActionsCellProps) => (
+  <EuiFlexGroup alignItems="center" gutterSize="xs">
+    <EuiFlexItem>
+      <OpenFlyoutRowControlColumn alert={alert} />
+    </EuiFlexItem>
+    <EuiFlexItem>
+      <MoreActionsRowControlColumn ecsAlert={ecsAlert} />
+    </EuiFlexItem>
+  </EuiFlexGroup>
+));
 
 ActionsCell.displayName = 'ActionsCell';
diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/more_actions_row_control_column.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/more_actions_row_control_column.test.tsx
new file mode 100644
index 0000000000000..96dfafcbdbe2f
--- /dev/null
+++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/more_actions_row_control_column.test.tsx
@@ -0,0 +1,131 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { render } from '@testing-library/react';
+import {
+  MORE_ACTIONS_BUTTON_TEST_ID,
+  MoreActionsRowControlColumn,
+} from './more_actions_row_control_column';
+import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs';
+import { useKibana } from '../../../../common/lib/kibana';
+import { mockCasesContract } from '@kbn/cases-plugin/public/mocks';
+import { useAlertsPrivileges } from '../../../containers/detection_engine/alerts/use_alerts_privileges';
+
+jest.mock('../../../../common/lib/kibana');
+jest.mock('../../../containers/detection_engine/alerts/use_alerts_privileges');
+
+describe('MoreActionsRowControlColumn', () => {
+  it('should render component with all options', () => {
+    (useAlertsPrivileges as jest.Mock).mockReturnValue({ hasIndexWrite: true });
+    (useKibana as jest.Mock).mockReturnValue({
+      services: {
+        cases: {
+          ...mockCasesContract(),
+          helpers: {
+            canUseCases: jest.fn().mockReturnValue({
+              read: true,
+              createComment: true,
+            }),
+            getRuleIdFromEvent: jest.fn(),
+          },
+        },
+      },
+    });
+
+    const ecsAlert: Ecs = {
+      _id: '_id',
+      _index: '_index',
+      event: { kind: ['signal'] },
+      kibana: { alert: { workflow_tags: [] } },
+    };
+
+    const { getByTestId } = render(<MoreActionsRowControlColumn ecsAlert={ecsAlert} />);
+
+    const button = getByTestId(MORE_ACTIONS_BUTTON_TEST_ID);
+    expect(button).toBeInTheDocument();
+
+    button.click();
+
+    expect(getByTestId('add-to-existing-case-action')).toBeInTheDocument();
+    expect(getByTestId('add-to-new-case-action')).toBeInTheDocument();
+    expect(getByTestId('alert-tags-context-menu-item')).toBeInTheDocument();
+  });
+
+  it('should not show cases actions if user is not authorized', () => {
+    (useAlertsPrivileges as jest.Mock).mockReturnValue({ hasIndexWrite: true });
+    (useKibana as jest.Mock).mockReturnValue({
+      services: {
+        cases: {
+          ...mockCasesContract(),
+          helpers: {
+            canUseCases: jest.fn().mockReturnValue({
+              read: false,
+              createComment: false,
+            }),
+            getRuleIdFromEvent: jest.fn(),
+          },
+        },
+      },
+    });
+
+    const ecsAlert: Ecs = {
+      _id: '_id',
+      _index: '_index',
+      event: { kind: ['signal'] },
+      kibana: { alert: { workflow_tags: [] } },
+    };
+
+    const { getByTestId, queryByTestId } = render(
+      <MoreActionsRowControlColumn ecsAlert={ecsAlert} />
+    );
+
+    const button = getByTestId(MORE_ACTIONS_BUTTON_TEST_ID);
+    expect(button).toBeInTheDocument();
+
+    button.click();
+
+    expect(queryByTestId('add-to-existing-case-action')).not.toBeInTheDocument();
+    expect(queryByTestId('add-to-new-case-action')).not.toBeInTheDocument();
+  });
+
+  it('should not show tags actions if user is not authorized', () => {
+    (useAlertsPrivileges as jest.Mock).mockReturnValue({ hasIndexWrite: false });
+    (useKibana as jest.Mock).mockReturnValue({
+      services: {
+        cases: {
+          ...mockCasesContract(),
+          helpers: {
+            canUseCases: jest.fn().mockReturnValue({
+              read: true,
+              createComment: true,
+            }),
+            getRuleIdFromEvent: jest.fn(),
+          },
+        },
+      },
+    });
+
+    const ecsAlert: Ecs = {
+      _id: '_id',
+      _index: '_index',
+      event: { kind: ['signal'] },
+      kibana: { alert: { workflow_tags: [] } },
+    };
+
+    const { getByTestId, queryByTestId } = render(
+      <MoreActionsRowControlColumn ecsAlert={ecsAlert} />
+    );
+
+    const button = getByTestId(MORE_ACTIONS_BUTTON_TEST_ID);
+    expect(button).toBeInTheDocument();
+
+    button.click();
+
+    expect(queryByTestId('alert-tags-context-menu-item')).not.toBeInTheDocument();
+  });
+});
diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/more_actions_row_control_column.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/more_actions_row_control_column.tsx
new file mode 100644
index 0000000000000..3075efbc8b338
--- /dev/null
+++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/more_actions_row_control_column.tsx
@@ -0,0 +1,102 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { memo, useCallback, useMemo, useState } from 'react';
+import { EuiButtonIcon, EuiContextMenu, EuiPopover } from '@elastic/eui';
+import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs';
+import { i18n } from '@kbn/i18n';
+import { useAlertTagsActions } from '../../alerts_table/timeline_actions/use_alert_tags_actions';
+import { useAddToCaseActions } from '../../alerts_table/timeline_actions/use_add_to_case_actions';
+
+export const MORE_ACTIONS_BUTTON_TEST_ID = 'alert-summary-table-row-action-more-actions';
+
+export const MORE_ACTIONS_BUTTON_ARIA_LABEL = i18n.translate(
+  'xpack.securitySolution.alertSummary.table.moreActionsAriaLabel',
+  {
+    defaultMessage: 'More actions',
+  }
+);
+export const ADD_TO_CASE_ARIA_LABEL = i18n.translate(
+  'xpack.securitySolution.alertSummary.table.attachToCaseAriaLabel',
+  {
+    defaultMessage: 'Attach alert to case',
+  }
+);
+
+export interface MoreActionsRowControlColumnProps {
+  /**
+   * Alert data
+   * The Ecs type is @deprecated but needed for the case actions within the more action dropdown
+   */
+  ecsAlert: Ecs;
+}
+
+/**
+ * Renders a horizontal 3-dot button which displays a context menu when clicked.
+ * This is used in the AI for SOC alert summary table.
+ * The following options are available:
+ * - add to existing case
+ * - add to new case
+ * - apply alert tags
+ */
+export const MoreActionsRowControlColumn = memo(
+  ({ ecsAlert }: MoreActionsRowControlColumnProps) => {
+    const [isPopoverOpen, setIsPopoverOpen] = useState(false);
+
+    const togglePopover = useCallback(() => setIsPopoverOpen((value) => !value), []);
+    const closePopover = useCallback(() => setIsPopoverOpen(false), []);
+
+    const button = useMemo(
+      () => (
+        <EuiButtonIcon
+          aria-label={MORE_ACTIONS_BUTTON_ARIA_LABEL}
+          data-test-subj={MORE_ACTIONS_BUTTON_TEST_ID}
+          iconType="boxesHorizontal"
+          onClick={togglePopover}
+        />
+      ),
+      [togglePopover]
+    );
+
+    const { addToCaseActionItems } = useAddToCaseActions({
+      ecsData: ecsAlert,
+      onMenuItemClick: closePopover,
+      isActiveTimelines: false,
+      ariaLabel: ADD_TO_CASE_ARIA_LABEL,
+      isInDetections: true,
+    });
+
+    const { alertTagsItems, alertTagsPanels } = useAlertTagsActions({
+      closePopover,
+      ecsRowData: ecsAlert,
+    });
+
+    const panels = useMemo(
+      () => [
+        {
+          id: 0,
+          items: [...addToCaseActionItems, ...alertTagsItems],
+        },
+        ...alertTagsPanels,
+      ],
+      [addToCaseActionItems, alertTagsItems, alertTagsPanels]
+    );
+
+    return (
+      <EuiPopover
+        button={button}
+        closePopover={togglePopover}
+        isOpen={isPopoverOpen}
+        panelPaddingSize="none"
+      >
+        <EuiContextMenu initialPanelId={0} panels={panels} size="s" />
+      </EuiPopover>
+    );
+  }
+);
+
+MoreActionsRowControlColumn.displayName = 'MoreActionsRowControlColumn';
diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/open_flyout_row_control_column.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/open_flyout_row_control_column.test.tsx
new file mode 100644
index 0000000000000..59c4e53851a72
--- /dev/null
+++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/open_flyout_row_control_column.test.tsx
@@ -0,0 +1,61 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { render } from '@testing-library/react';
+import type { Alert } from '@kbn/alerting-types';
+import {
+  OpenFlyoutRowControlColumn,
+  ROW_ACTION_FLYOUT_ICON_TEST_ID,
+} from './open_flyout_row_control_column';
+import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
+import { IOCPanelKey } from '../../../../flyout/ai_for_soc/constants/panel_keys';
+
+jest.mock('@kbn/expandable-flyout');
+
+describe('OpenFlyoutRowControlColumn', () => {
+  it('should render button icon', () => {
+    (useExpandableFlyoutApi as jest.Mock).mockReturnValue({
+      openFlyout: jest.fn(),
+    });
+
+    const alert: Alert = {
+      _id: '_id',
+      _index: '_index',
+    };
+
+    const { getByTestId } = render(<OpenFlyoutRowControlColumn alert={alert} />);
+
+    expect(getByTestId(ROW_ACTION_FLYOUT_ICON_TEST_ID)).toBeInTheDocument();
+  });
+
+  it('should open flyout after click', () => {
+    const openFlyout = jest.fn();
+    (useExpandableFlyoutApi as jest.Mock).mockReturnValue({
+      openFlyout,
+    });
+
+    const alert: Alert = {
+      _id: '_id',
+      _index: '_index',
+    };
+
+    const { getByTestId } = render(<OpenFlyoutRowControlColumn alert={alert} />);
+
+    getByTestId(ROW_ACTION_FLYOUT_ICON_TEST_ID).click();
+
+    expect(openFlyout).toHaveBeenCalledWith({
+      right: {
+        id: IOCPanelKey,
+        params: {
+          id: alert._id,
+          indexName: alert._index,
+        },
+      },
+    });
+  });
+});
diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/open_flyout_row_control_column.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/open_flyout_row_control_column.tsx
new file mode 100644
index 0000000000000..dcfc0fc7ebfa5
--- /dev/null
+++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/open_flyout_row_control_column.tsx
@@ -0,0 +1,57 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { memo, useCallback } from 'react';
+import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
+import { EuiButtonIcon } from '@elastic/eui';
+import type { Alert } from '@kbn/alerting-types';
+import { i18n } from '@kbn/i18n';
+import { IOCPanelKey } from '../../../../flyout/ai_for_soc/constants/panel_keys';
+
+export const ROW_ACTION_FLYOUT_ICON_TEST_ID = 'alert-summary-table-row-action-flyout-icon';
+
+export interface ActionsCellProps {
+  /**
+   * Alert data passed from the renderCellValue callback via the AlertWithLegacyFormats interface
+   */
+  alert: Alert;
+}
+
+/**
+ * Renders a icon to open the AI for SOC alert summary flyout.
+ */
+export const OpenFlyoutRowControlColumn = memo(({ alert }: ActionsCellProps) => {
+  const { openFlyout } = useExpandableFlyoutApi();
+  const onOpenFlyout = useCallback(
+    () =>
+      openFlyout({
+        right: {
+          id: IOCPanelKey,
+          params: {
+            id: alert._id,
+            indexName: alert._index,
+          },
+        },
+      }),
+    [alert, openFlyout]
+  );
+
+  return (
+    <EuiButtonIcon
+      aria-label={i18n.translate('xpack.securitySolution.alertSummary.table.flyoutIcon', {
+        defaultMessage: 'Open flyout',
+      })}
+      color="primary"
+      data-test-subj={ROW_ACTION_FLYOUT_ICON_TEST_ID}
+      iconType="expand"
+      onClick={onOpenFlyout}
+      size="xs"
+    />
+  );
+});
+
+OpenFlyoutRowControlColumn.displayName = 'OpenFlyoutRowControlColumn';
diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/table.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/table.tsx
index 0efdd73bed0e2..bba449d9b140f 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/table.tsx
+++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/table.tsx
@@ -72,7 +72,7 @@ const columns: EuiDataGridProps['columns'] = [
   },
 ];
 
-const ACTION_COLUMN_WIDTH = 64; // px
+const ACTION_COLUMN_WIDTH = 72; // px
 const ALERT_TABLE_CONSUMERS: AlertsTableProps['consumers'] = [AlertConsumers.SIEM];
 const RULE_TYPE_IDS = [ESQL_RULE_TYPE_ID, QUERY_RULE_TYPE_ID];
 const ROW_HEIGHTS_OPTIONS = { defaultHeight: 40 };
diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/components/take_action_button.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/components/take_action_button.test.tsx
new file mode 100644
index 0000000000000..103742dc56864
--- /dev/null
+++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/components/take_action_button.test.tsx
@@ -0,0 +1,128 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { render } from '@testing-library/react';
+import { useKibana } from '../../../common/lib/kibana';
+import { mockCasesContract } from '@kbn/cases-plugin/public/mocks';
+import { TAKE_ACTION_BUTTON_TEST_ID, TakeActionButton } from './take_action_button';
+import { useAlertsPrivileges } from '../../../detections/containers/detection_engine/alerts/use_alerts_privileges';
+import { useAIForSOCDetailsContext } from '../context';
+
+jest.mock('../../../common/lib/kibana');
+jest.mock('../../../detections/containers/detection_engine/alerts/use_alerts_privileges');
+jest.mock('../context');
+
+describe('TakeActionButton', () => {
+  it('should render component with all options', () => {
+    (useAlertsPrivileges as jest.Mock).mockReturnValue({ hasIndexWrite: true });
+    (useKibana as jest.Mock).mockReturnValue({
+      services: {
+        cases: {
+          ...mockCasesContract(),
+          helpers: {
+            canUseCases: jest.fn().mockReturnValue({
+              read: true,
+              createComment: true,
+            }),
+            getRuleIdFromEvent: jest.fn(),
+          },
+        },
+      },
+    });
+    (useAIForSOCDetailsContext as jest.Mock).mockReturnValue({
+      dataAsNestedObject: {
+        _id: '_id',
+        _index: '_index',
+        event: { kind: ['signal'] },
+        kibana: { alert: { workflow_tags: [] } },
+      },
+    });
+
+    const { getByTestId } = render(<TakeActionButton />);
+
+    const button = getByTestId(TAKE_ACTION_BUTTON_TEST_ID);
+    expect(button).toBeInTheDocument();
+
+    button.click();
+
+    expect(getByTestId('add-to-existing-case-action')).toBeInTheDocument();
+    expect(getByTestId('add-to-new-case-action')).toBeInTheDocument();
+    expect(getByTestId('alert-tags-context-menu-item')).toBeInTheDocument();
+  });
+
+  it('should not show cases actions if user is not authorized', () => {
+    (useAlertsPrivileges as jest.Mock).mockReturnValue({ hasIndexWrite: true });
+    (useKibana as jest.Mock).mockReturnValue({
+      services: {
+        cases: {
+          ...mockCasesContract(),
+          helpers: {
+            canUseCases: jest.fn().mockReturnValue({
+              read: false,
+              createComment: false,
+            }),
+            getRuleIdFromEvent: jest.fn(),
+          },
+        },
+      },
+    });
+    (useAIForSOCDetailsContext as jest.Mock).mockReturnValue({
+      dataAsNestedObject: {
+        _id: '_id',
+        _index: '_index',
+        event: { kind: ['signal'] },
+        kibana: { alert: { workflow_tags: [] } },
+      },
+    });
+
+    const { getByTestId, queryByTestId } = render(<TakeActionButton />);
+
+    const button = getByTestId(TAKE_ACTION_BUTTON_TEST_ID);
+    expect(button).toBeInTheDocument();
+
+    button.click();
+
+    expect(queryByTestId('add-to-existing-case-action')).not.toBeInTheDocument();
+    expect(queryByTestId('add-to-new-case-action')).not.toBeInTheDocument();
+  });
+
+  it('should not show tags actions if user is not authorized', () => {
+    (useAlertsPrivileges as jest.Mock).mockReturnValue({ hasIndexWrite: false });
+    (useKibana as jest.Mock).mockReturnValue({
+      services: {
+        cases: {
+          ...mockCasesContract(),
+          helpers: {
+            canUseCases: jest.fn().mockReturnValue({
+              read: true,
+              createComment: true,
+            }),
+            getRuleIdFromEvent: jest.fn(),
+          },
+        },
+      },
+    });
+    (useAIForSOCDetailsContext as jest.Mock).mockReturnValue({
+      dataAsNestedObject: {
+        _id: '_id',
+        _index: '_index',
+        event: { kind: ['signal'] },
+        kibana: { alert: { workflow_tags: [] } },
+      },
+    });
+
+    const { getByTestId, queryByTestId } = render(<TakeActionButton />);
+
+    const button = getByTestId(TAKE_ACTION_BUTTON_TEST_ID);
+    expect(button).toBeInTheDocument();
+
+    button.click();
+
+    expect(queryByTestId('alert-tags-context-menu-item')).not.toBeInTheDocument();
+  });
+});
diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/components/take_action_button.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/components/take_action_button.tsx
new file mode 100644
index 0000000000000..ce353ed019b8b
--- /dev/null
+++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/components/take_action_button.tsx
@@ -0,0 +1,98 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { memo, useCallback, useMemo, useState } from 'react';
+import { EuiButton, EuiContextMenu, EuiPopover } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { useAIForSOCDetailsContext } from '../context';
+import { useAddToCaseActions } from '../../../detections/components/alerts_table/timeline_actions/use_add_to_case_actions';
+import { useAlertTagsActions } from '../../../detections/components/alerts_table/timeline_actions/use_alert_tags_actions';
+
+export const TAKE_ACTION_BUTTON_TEST_ID = 'alert-summary-flyout-take-action';
+
+export const TAKE_ACTION_BUTTON = i18n.translate(
+  'xpack.securitySolution.alertSummary.flyout.takeActionsAriaLabel',
+  {
+    defaultMessage: 'Take action',
+  }
+);
+export const ADD_TO_CASE_ARIA_LABEL = i18n.translate(
+  'xpack.securitySolution.alertSummary.flyout.attachToCaseAriaLabel',
+  {
+    defaultMessage: 'Attach alert to case',
+  }
+);
+
+/**
+ * Take action button in the panel footer.
+ * This is used in the AI for SOC alert summary page.
+ * The following options are available:
+ * - add to existing case
+ * - add to new case
+ * - apply alert tags
+ */
+export const TakeActionButton = memo(() => {
+  const [isPopoverOpen, setIsPopoverOpen] = useState(false);
+
+  const { dataAsNestedObject } = useAIForSOCDetailsContext();
+
+  const togglePopover = useCallback(() => setIsPopoverOpen((value) => !value), []);
+  const closePopover = useCallback(() => setIsPopoverOpen(false), []);
+
+  const button = useMemo(
+    () => (
+      <EuiButton
+        aria-label={TAKE_ACTION_BUTTON}
+        data-test-subj={TAKE_ACTION_BUTTON_TEST_ID}
+        fill
+        iconSide="right"
+        iconType="arrowDown"
+        onClick={togglePopover}
+      >
+        {TAKE_ACTION_BUTTON}
+      </EuiButton>
+    ),
+    [togglePopover]
+  );
+
+  const { addToCaseActionItems } = useAddToCaseActions({
+    ecsData: dataAsNestedObject,
+    onMenuItemClick: closePopover,
+    isActiveTimelines: false,
+    ariaLabel: ADD_TO_CASE_ARIA_LABEL,
+    isInDetections: true,
+  });
+
+  const { alertTagsItems, alertTagsPanels } = useAlertTagsActions({
+    closePopover,
+    ecsRowData: dataAsNestedObject,
+  });
+
+  const panels = useMemo(
+    () => [
+      {
+        id: 0,
+        items: [...addToCaseActionItems, ...alertTagsItems],
+      },
+      ...alertTagsPanels,
+    ],
+    [addToCaseActionItems, alertTagsItems, alertTagsPanels]
+  );
+
+  return (
+    <EuiPopover
+      button={button}
+      closePopover={togglePopover}
+      isOpen={isPopoverOpen}
+      panelPaddingSize="none"
+    >
+      <EuiContextMenu initialPanelId={0} panels={panels} size="s" />
+    </EuiPopover>
+  );
+});
+
+TakeActionButton.displayName = 'TakeActionButton';
diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/context.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/context.tsx
index c0765785aec0f..690c4d67668b8 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/context.tsx
+++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/context.tsx
@@ -7,6 +7,7 @@
 
 import React, { createContext, memo, useContext, useMemo } from 'react';
 import type { BrowserFields, TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common';
+import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs';
 import type { SearchHit } from '../../../common/search_strategy';
 import type { GetFieldsData } from '../document_details/shared/hooks/use_get_fields_data';
 import { FlyoutLoading } from '../shared/components/flyout_loading';
@@ -31,6 +32,10 @@ export interface AIForSOCDetailsContext {
    * An object containing fields by type
    */
   browserFields: BrowserFields;
+  /**
+   * An object with top level fields from the ECS object
+   */
+  dataAsNestedObject: Ecs;
   /**
    * Retrieves searchHit values for the provided field
    */
@@ -55,24 +60,39 @@ export type AIForSOCDetailsProviderProps = {
 
 export const AIForSOCDetailsProvider = memo(
   ({ id, indexName, children }: AIForSOCDetailsProviderProps) => {
-    const { browserFields, dataFormattedForFieldBrowser, getFieldsData, loading, searchHit } =
-      useEventDetails({
-        eventId: id,
-        indexName,
-      });
+    const {
+      browserFields,
+      dataAsNestedObject,
+      dataFormattedForFieldBrowser,
+      getFieldsData,
+      loading,
+      searchHit,
+    } = useEventDetails({
+      eventId: id,
+      indexName,
+    });
     const contextValue = useMemo(
       () =>
-        dataFormattedForFieldBrowser && id && indexName && searchHit
+        dataFormattedForFieldBrowser && dataAsNestedObject && id && indexName && searchHit
           ? {
               browserFields,
               dataFormattedForFieldBrowser,
+              dataAsNestedObject,
               eventId: id,
               getFieldsData,
               indexName,
               searchHit,
             }
           : undefined,
-      [browserFields, dataFormattedForFieldBrowser, getFieldsData, id, indexName, searchHit]
+      [
+        browserFields,
+        dataAsNestedObject,
+        dataFormattedForFieldBrowser,
+        getFieldsData,
+        id,
+        indexName,
+        searchHit,
+      ]
     );
 
     if (loading) {
diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/footer.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/footer.tsx
index fc2d60fe07bf4..c117c0b780b83 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/footer.tsx
+++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/footer.tsx
@@ -5,22 +5,25 @@
  * 2.0.
  */
 
-import React from 'react';
+import React, { memo } from 'react';
 import { EuiFlexGroup, EuiFlexItem, EuiFlyoutFooter, EuiPanel } from '@elastic/eui';
+import { TakeActionButton } from './components/take_action_button';
 
 export const FLYOUT_FOOTER_TEST_ID = 'ai-for-soc-alert-flyout-footer';
 
 /**
  * Bottom section of the flyout that contains the take action button
  */
-export const PanelFooter = () => (
+export const PanelFooter = memo(() => (
   <EuiFlyoutFooter data-test-subj={FLYOUT_FOOTER_TEST_ID}>
     <EuiPanel color="transparent">
       <EuiFlexGroup justifyContent="flexEnd" alignItems="center">
-        <EuiFlexItem grow={false} />
+        <EuiFlexItem grow={false}>
+          <TakeActionButton />
+        </EuiFlexItem>
       </EuiFlexGroup>
     </EuiPanel>
   </EuiFlyoutFooter>
-);
+));
 
 PanelFooter.displayName = 'PanelFooter';


Reviews:
user: login: PhilippeOberti
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T19:19:50Z
user: login: PhilippeOberti
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T19:20:13Z
user: login: kqualters-elastic
body: LGTM 👍 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T17:33:41Z
user: login: PhilippeOberti
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T17:35:05Z
user: login: PhilippeOberti
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T17:43:31Z

Review comments:
diff_hunk: @@ -0,0 +1,62 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { memo, useCallback } from 'react';
+import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
+import { EuiButtonIcon } from '@elastic/eui';
+import type { Alert } from '@kbn/alerting-types';
+import { i18n } from '@kbn/i18n';
+import { IOCPanelKey } from '../../../../flyout/ai_for_soc/constants/panel_keys';
+
+export const ROW_ACTION_FLYOUT_ICON_TEST_ID = 'alert-summary-table-row-action-flyout-icon';
+
+export interface ActionsCellProps {
+  /**
+   * Alert data passed from the renderCellValue callback via the AlertWithLegacyFormats interface
+   */
+  alert: Alert;
+}
+
+/**
+ * Component used in the AI for SOC alert summary table.
+ * It is passed to the renderActionsCell property of the EuiDataGrid.
+ * It renders all the icons in the row action icons:
+ * - open flyout
+ * - assistant (soon)
+ * - more actions (soon)
path: x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/open_flyout_row_control_column.tsx
user: login: PhilippeOberti
body: Update this documentation to `Renders a icon to open the AI for SOC alert summary flyout.`
created_at: 2025-04-10T19:19:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -5,12 +5,12 @@
  * 2.0.
  */
 
-import React, { memo, useCallback } from 'react';
-import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
-import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+import React, { memo } from 'react';
+import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
 import type { Alert } from '@kbn/alerting-types';
-import { i18n } from '@kbn/i18n';
-import { IOCPanelKey } from '../../../../flyout/ai_for_soc/constants/panel_keys';
+import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs';
+import { OpenFlyoutRowControlColumn } from './open_flyout_row_control_column';
+import { MoreActionsRowControlColumn } from './more_actions_row_control_column';
 
 export const ROW_ACTION_FLYOUT_ICON_TEST_ID = 'alert-summary-table-row-action-flyout-icon';
path: x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/actions_cell.tsx
user: login: PhilippeOberti
body: Remove unused constant
created_at: 2025-04-10T19:20:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,99 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type { FC } from 'react';
+import React, { useCallback, useMemo, useState } from 'react';
+import { EuiButton, EuiContextMenu, EuiPopover } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { useAIForSOCDetailsContext } from '../context';
+import { useAddToCaseActions } from '../../../detections/components/alerts_table/timeline_actions/use_add_to_case_actions';
+import { useAlertTagsActions } from '../../../detections/components/alerts_table/timeline_actions/use_alert_tags_actions';
+
+export const TAKE_ACTION_BUTTON_TEST_ID = 'alert-summary-flyout-take-action';
+
+export const TAKE_ACTION_BUTTON = i18n.translate(
+  'xpack.securitySolution.alertSummary.flyout.takeActionsAriaLabel',
+  {
+    defaultMessage: 'Take action',
+  }
+);
+export const ADD_TO_CASE_ARIA_LABEL = i18n.translate(
+  'xpack.securitySolution.alertSummary.flyout.attachToCaseAriaLabel',
+  {
+    defaultMessage: 'Attach alert to case',
+  }
+);
+
+/**
+ * Take action button in the panel footer.
+ * This is used in the AI for SOC alert summary page.
+ * The following options are available:
+ * - add to existing case
+ * - add to new case
+ * - apply alert tags
+ */
+export const TakeActionButton: FC = () => {
path: x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/components/take_action_button.tsx
user: login: kqualters-elastic
body: any reason you memo'ed the others but not this one?
created_at: 2025-04-14T17:33:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,99 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type { FC } from 'react';
+import React, { useCallback, useMemo, useState } from 'react';
+import { EuiButton, EuiContextMenu, EuiPopover } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { useAIForSOCDetailsContext } from '../context';
+import { useAddToCaseActions } from '../../../detections/components/alerts_table/timeline_actions/use_add_to_case_actions';
+import { useAlertTagsActions } from '../../../detections/components/alerts_table/timeline_actions/use_alert_tags_actions';
+
+export const TAKE_ACTION_BUTTON_TEST_ID = 'alert-summary-flyout-take-action';
+
+export const TAKE_ACTION_BUTTON = i18n.translate(
+  'xpack.securitySolution.alertSummary.flyout.takeActionsAriaLabel',
+  {
+    defaultMessage: 'Take action',
+  }
+);
+export const ADD_TO_CASE_ARIA_LABEL = i18n.translate(
+  'xpack.securitySolution.alertSummary.flyout.attachToCaseAriaLabel',
+  {
+    defaultMessage: 'Attach alert to case',
+  }
+);
+
+/**
+ * Take action button in the panel footer.
+ * This is used in the AI for SOC alert summary page.
+ * The following options are available:
+ * - add to existing case
+ * - add to new case
+ * - apply alert tags
+ */
+export const TakeActionButton: FC = () => {
path: x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/components/take_action_button.tsx
user: login: PhilippeOberti
body: Mistake on my end, will fix as I rebase against latest `main`, thanks for catching this!
created_at: 2025-04-14T17:35:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,99 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type { FC } from 'react';
+import React, { useCallback, useMemo, useState } from 'react';
+import { EuiButton, EuiContextMenu, EuiPopover } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { useAIForSOCDetailsContext } from '../context';
+import { useAddToCaseActions } from '../../../detections/components/alerts_table/timeline_actions/use_add_to_case_actions';
+import { useAlertTagsActions } from '../../../detections/components/alerts_table/timeline_actions/use_alert_tags_actions';
+
+export const TAKE_ACTION_BUTTON_TEST_ID = 'alert-summary-flyout-take-action';
+
+export const TAKE_ACTION_BUTTON = i18n.translate(
+  'xpack.securitySolution.alertSummary.flyout.takeActionsAriaLabel',
+  {
+    defaultMessage: 'Take action',
+  }
+);
+export const ADD_TO_CASE_ARIA_LABEL = i18n.translate(
+  'xpack.securitySolution.alertSummary.flyout.attachToCaseAriaLabel',
+  {
+    defaultMessage: 'Attach alert to case',
+  }
+);
+
+/**
+ * Take action button in the panel footer.
+ * This is used in the AI for SOC alert summary page.
+ * The following options are available:
+ * - add to existing case
+ * - add to new case
+ * - apply alert tags
+ */
+export const TakeActionButton: FC = () => {
path: x-pack/solutions/security/plugins/security_solution/public/flyout/ai_for_soc/components/take_action_button.tsx
user: login: PhilippeOberti
body: fixed!
created_at: 2025-04-14T17:43:31Z
author_association: CONTRIBUTOR

PR comments:
user: login: elasticmachine
created_at: 2025-04-10T18:52:09Z
body: Pinging @elastic/security-threat-hunting-investigations (Team:Threat Hunting:Investigations)
author_association: CONTRIBUTOR
user: login: elasticmachine
created_at: 2025-04-14T19:24:23Z
body: ## :green_heart: Build Succeeded
* [Buildkite Build](https://buildkite.com/elastic/kibana-pull-request/builds/292898)
* Commit: 10c145259f0aa6e9882222866848a611b8e0b074

### Metrics [[docs](https://www.elastic.co/guide/en/kibana/master/ci-metrics.html)]
#### Module Count
> Fewer modules leads to a faster build time


| id | [before](https://github.com/elastic/kibana/commit/4cd937642248311d4dd41ec78b3f48d41a0213ab) | [after](https://github.com/elastic/kibana/commit/10c145259f0aa6e9882222866848a611b8e0b074) | diff |
| --- | --- | --- | --- |
| `securitySolution` | 7218 | 7221 | +3 |

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


| id | [before](https://github.com/elastic/kibana/commit/4cd937642248311d4dd41ec78b3f48d41a0213ab) | [after](https://github.com/elastic/kibana/commit/10c145259f0aa6e9882222866848a611b8e0b074) | diff |
| --- | --- | --- | --- |
| `securitySolution` | 9.0MB | 9.0MB | +2.3KB |

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


| id | [before](https://github.com/elastic/kibana/commit/4cd937642248311d4dd41ec78b3f48d41a0213ab) | [after](https://github.com/elastic/kibana/commit/10c145259f0aa6e9882222866848a611b8e0b074) | diff |
| --- | --- | --- | --- |
| `securitySolution` | 88.8KB | 88.8KB | +1.0B |



### History
* :green_heart: [Build #292428](https://buildkite.com/elastic/kibana-pull-request/builds/292428) succeeded 7b3a5418b8669df9ac8b97b22524a28fa5377c40
* :green_heart: [Build #292085](https://buildkite.com/elastic/kibana-pull-request/builds/292085) succeeded 6b754c40ca172b57abf5af6a6f31e3baa4863ecf

<!--buildkite-pr-comment-kibana-pull-request
{"builds":[{"buildStatus":{"state":"passed","success":true,"hasRetries":false,"hasNonPreemptionRetries":false},"url":"https://buildkite.com/elastic/kibana-pull-request/builds/292898","number":292898,"commit":"10c145259f0aa6e9882222866848a611b8e0b074"},{"buildStatus":{"state":"passed","success":true,"hasRetries":false,"hasNonPreemptionRetries":false},"url":"https://buildkite.com/elastic/kibana-pull-request/builds/292428","number":292428,"commit":"7b3a5418b8669df9ac8b97b22524a28fa5377c40"},{"buildStatus":{"state":"passed","success":true,"hasRetries":false,"hasNonPreemptionRetries":false},"url":"https://buildkite.com/elastic/kibana-pull-request/builds/292085","number":292085,"commit":"6b754c40ca172b57abf5af6a6f31e3baa4863ecf"}],"number":292898}
buildkite-pr-comment-->
author_association: CONTRIBUTOR