diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 5a9e8bc585119..525da9d832b53 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -381,8 +381,9 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib
 **/*.scss  @elastic/kibana-design
 #CC# /packages/kbn-ui-framework/ @elastic/kibana-design
 
-# Core design
+# Core UI design
 /src/plugins/dashboard/**/*.scss @elastic/kibana-core-ui-designers
+/src/plugins/embeddable/**/*.scss @elastic/kibana-core-ui-designers
 /x-pack/plugins/canvas/**/*.scss @elastic/kibana-core-ui-designers
 /x-pack/plugins/spaces/**/*.scss @elastic/kibana-core-ui-designers
 /x-pack/plugins/security/**/*.scss @elastic/kibana-core-ui-designers
diff --git a/.github/ISSUE_TEMPLATE/Bug_report_security_solution.md b/.github/ISSUE_TEMPLATE/Bug_report_security_solution.md
index 059e1d267c286..7a0514bca621d 100644
--- a/.github/ISSUE_TEMPLATE/Bug_report_security_solution.md
+++ b/.github/ISSUE_TEMPLATE/Bug_report_security_solution.md
@@ -1,38 +1,38 @@
----
-name: Bug report for Security Solution
-about: Help us identify bugs in Elastic Security, SIEM, and Endpoint so we can fix them!
-title: '[Security Solution]'
-labels: 'Team: SecuritySolution'
----
-
-**Describe the bug:**
-
-**Kibana/Elasticsearch Stack version:**
-
-**Server OS version:**
-
-**Browser and Browser OS versions:**
-
-**Elastic Endpoint version:**
-
-**Original install method (e.g. download page, yum, from source, etc.):**
-
-**Functional Area (e.g. Endpoint management, timelines, resolver, etc.):**
-
-**Steps to reproduce:**
-
-1.
-2.
-3.
-
-**Current behavior:**
-
-**Expected behavior:**
-
-**Screenshots (if relevant):**
-
-**Errors in browser console (if relevant):**
-
-**Provide logs and/or server output (if relevant):**
-
-**Any additional context (logs, chat logs, magical formulas, etc.):**
+---
+name: Bug report for Security Solution
+about: Help us identify bugs in Elastic Security, SIEM, and Endpoint so we can fix them!
+title: '[Security Solution]'
+labels: 'bug, Team: SecuritySolution'
+---
+
+**Describe the bug:**
+
+**Kibana/Elasticsearch Stack version:**
+
+**Server OS version:**
+
+**Browser and Browser OS versions:**
+
+**Elastic Endpoint version:**
+
+**Original install method (e.g. download page, yum, from source, etc.):**
+
+**Functional Area (e.g. Endpoint management, timelines, resolver, etc.):**
+
+**Steps to reproduce:**
+
+1.
+2.
+3.
+
+**Current behavior:**
+
+**Expected behavior:**
+
+**Screenshots (if relevant):**
+
+**Errors in browser console (if relevant):**
+
+**Provide logs and/or server output (if relevant):**
+
+**Any additional context (logs, chat logs, magical formulas, etc.):**
diff --git a/.github/ISSUE_TEMPLATE/v8_breaking_change.md b/.github/ISSUE_TEMPLATE/v8_breaking_change.md
index 99f779c288f5b..c91b937586a09 100644
--- a/.github/ISSUE_TEMPLATE/v8_breaking_change.md
+++ b/.github/ISSUE_TEMPLATE/v8_breaking_change.md
@@ -2,7 +2,7 @@
 name: 8.0 Breaking change
 about: Breaking changes from 7.x -> 8.0
 title: "[Breaking change]"
-labels: Team:Elasticsearch UI, Feature:Upgrade Assistant
+labels: Team:Elasticsearch UI, Feature:Upgrade Assistant, Breaking Change
 assignees: ''
 
 ---
@@ -11,15 +11,16 @@ assignees: ''
 
 **Which release will ship the breaking change?**
 
-<!-- e.g., v7.6.2 -->
+8.0
 
 **Describe the change. How will it manifest to users?**
 
-**What percentage of users will be affected?**
+**How many users will be affected?**
 
-<!-- e.g., Roughly 75% will need to make changes to x. -->
+<!-- e.g., Based on telemetry data, roughly 75% of our users will need to make changes to x -->
+<!-- e.g., A majority of users will need to make changes to x. -->
 
-**What can users to do to address the change manually?**
+**What can users do to address the change manually?**
 
 <!-- If applicable, describe the manual workaround -->
 
diff --git a/.telemetryrc.json b/.telemetryrc.json
index 3d1b0df1d8f93..0f1530c6225d6 100644
--- a/.telemetryrc.json
+++ b/.telemetryrc.json
@@ -7,5 +7,10 @@
       "src/plugins/testbed/",
       "src/plugins/kibana_utils/"
     ]
+  },
+  {
+    "output": "src/plugins/telemetry/schema/legacy_plugins.json",
+    "root": "src/legacy/server/",
+    "exclude": []
   }
 ]
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror._constructor_.md
index f8966572afbb6..051414eac7585 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror._constructor_.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror._constructor_.md
@@ -9,13 +9,13 @@ Constructs a new instance of the `PainlessError` class
 <b>Signature:</b>
 
 ```typescript
-constructor(err: EsError, request: IKibanaSearchRequest);
+constructor(err: IEsError, request: IKibanaSearchRequest);
 ```
 
 ## Parameters
 
 |  Parameter | Type | Description |
 |  --- | --- | --- |
-|  err | <code>EsError</code> |  |
+|  err | <code>IEsError</code> |  |
 |  request | <code>IKibanaSearchRequest</code> |  |
 
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror.md
index 306211cd60259..6ab32f3fb1dfa 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror.md
@@ -7,7 +7,7 @@
 <b>Signature:</b>
 
 ```typescript
-export declare class PainlessError extends KbnError 
+export declare class PainlessError extends EsError 
 ```
 
 ## Constructors
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher._constructor_.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher._constructor_.md
index d36ebd0745e8d..214c795fda9d1 100644
--- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher._constructor_.md
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher._constructor_.md
@@ -9,12 +9,13 @@ Constructs a new instance of the `IndexPatternsFetcher` class
 <b>Signature:</b>
 
 ```typescript
-constructor(callDataCluster: LegacyAPICaller);
+constructor(elasticsearchClient: ElasticsearchClient, allowNoIndices?: boolean);
 ```
 
 ## Parameters
 
 |  Parameter | Type | Description |
 |  --- | --- | --- |
-|  callDataCluster | <code>LegacyAPICaller</code> |  |
+|  elasticsearchClient | <code>ElasticsearchClient</code> |  |
+|  allowNoIndices | <code>boolean</code> |  |
 
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.getfieldsforwildcard.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.getfieldsforwildcard.md
index 52382372d6d96..addd29916d81d 100644
--- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.getfieldsforwildcard.md
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.getfieldsforwildcard.md
@@ -13,7 +13,7 @@ getFieldsForWildcard(options: {
         pattern: string | string[];
         metaFields?: string[];
         fieldCapsOptions?: {
-            allowNoIndices: boolean;
+            allow_no_indices: boolean;
         };
     }): Promise<FieldDescriptor[]>;
 ```
@@ -22,7 +22,7 @@ getFieldsForWildcard(options: {
 
 |  Parameter | Type | Description |
 |  --- | --- | --- |
-|  options | <code>{</code><br/><code>        pattern: string &#124; string[];</code><br/><code>        metaFields?: string[];</code><br/><code>        fieldCapsOptions?: {</code><br/><code>            allowNoIndices: boolean;</code><br/><code>        };</code><br/><code>    }</code> |  |
+|  options | <code>{</code><br/><code>        pattern: string &#124; string[];</code><br/><code>        metaFields?: string[];</code><br/><code>        fieldCapsOptions?: {</code><br/><code>            allow_no_indices: boolean;</code><br/><code>        };</code><br/><code>    }</code> |  |
 
 <b>Returns:</b>
 
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.md
index f71a702f3381d..3ba3c862bf16a 100644
--- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.md
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.md
@@ -14,7 +14,7 @@ export declare class IndexPatternsFetcher
 
 |  Constructor | Modifiers | Description |
 |  --- | --- | --- |
-|  [(constructor)(callDataCluster)](./kibana-plugin-plugins-data-server.indexpatternsfetcher._constructor_.md) |  | Constructs a new instance of the <code>IndexPatternsFetcher</code> class |
+|  [(constructor)(elasticsearchClient, allowNoIndices)](./kibana-plugin-plugins-data-server.indexpatternsfetcher._constructor_.md) |  | Constructs a new instance of the <code>IndexPatternsFetcher</code> class |
 
 ## Methods
 
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution._constructor_.md
index 1d0c9f99169db..14a0f8818e903 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution._constructor_.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution._constructor_.md
@@ -9,12 +9,12 @@ Constructs a new instance of the `Execution` class
 <b>Signature:</b>
 
 ```typescript
-constructor(params: ExecutionParams<ExtraContext>);
+constructor(execution: ExecutionParams);
 ```
 
 ## Parameters
 
 |  Parameter | Type | Description |
 |  --- | --- | --- |
-|  params | <code>ExecutionParams&lt;ExtraContext&gt;</code> |  |
+|  execution | <code>ExecutionParams</code> |  |
 
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.context.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.context.md
index 732fe94d65617..e884db46563b5 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.context.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.context.md
@@ -9,5 +9,5 @@ Execution context - object that allows to do side-effects. Context is passed to
 <b>Signature:</b>
 
 ```typescript
-readonly context: ExecutionContext<Input, InspectorAdapters> & ExtraContext;
+readonly context: ExecutionContext<InspectorAdapters>;
 ```
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.contract.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.contract.md
index fa03297ea22a7..383e9ee3e81b8 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.contract.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.contract.md
@@ -9,5 +9,5 @@ Contract is a public representation of `Execution` instances. Contract we can re
 <b>Signature:</b>
 
 ```typescript
-readonly contract: ExecutionContract<ExtraContext, Input, Output, InspectorAdapters>;
+readonly contract: ExecutionContract<Input, Output, InspectorAdapters>;
 ```
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.params.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.execution.md
similarity index 67%
rename from docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.params.md
rename to docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.execution.md
index cd90bf6adab47..eebb5cf5440d5 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.params.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.execution.md
@@ -1,11 +1,11 @@
 <!-- Do not edit this file. It is automatically generated by API Documenter. -->
 
-[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [Execution](./kibana-plugin-plugins-expressions-public.execution.md) &gt; [params](./kibana-plugin-plugins-expressions-public.execution.params.md)
+[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [Execution](./kibana-plugin-plugins-expressions-public.execution.md) &gt; [execution](./kibana-plugin-plugins-expressions-public.execution.execution.md)
 
-## Execution.params property
+## Execution.execution property
 
 <b>Signature:</b>
 
 ```typescript
-readonly params: ExecutionParams<ExtraContext>;
+readonly execution: ExecutionParams;
 ```
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.interpret.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.interpret.md
index 31f38b7069812..24dee04861b4e 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.interpret.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.interpret.md
@@ -7,7 +7,7 @@
 <b>Signature:</b>
 
 ```typescript
-interpret<T>(ast: ExpressionAstNode, input: T, options?: ExpressionExecOptions): Promise<unknown>;
+interpret<T>(ast: ExpressionAstNode, input: T): Promise<unknown>;
 ```
 
 ## Parameters
@@ -16,7 +16,6 @@ interpret<T>(ast: ExpressionAstNode, input: T, options?: ExpressionExecOptions):
 |  --- | --- | --- |
 |  ast | <code>ExpressionAstNode</code> |  |
 |  input | <code>T</code> |  |
-|  options | <code>ExpressionExecOptions</code> |  |
 
 <b>Returns:</b>
 
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.md
index 4d227e6ab85b8..56b14e005adfb 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.md
@@ -7,25 +7,25 @@
 <b>Signature:</b>
 
 ```typescript
-export declare class Execution<ExtraContext extends Record<string, unknown> = Record<string, unknown>, Input = unknown, Output = unknown, InspectorAdapters extends Adapters = ExtraContext['inspectorAdapters'] extends object ? ExtraContext['inspectorAdapters'] : DefaultInspectorAdapters> 
+export declare class Execution<Input = unknown, Output = unknown, InspectorAdapters extends Adapters = ExpressionExecutionParams['inspectorAdapters'] extends object ? ExpressionExecutionParams['inspectorAdapters'] : DefaultInspectorAdapters> 
 ```
 
 ## Constructors
 
 |  Constructor | Modifiers | Description |
 |  --- | --- | --- |
-|  [(constructor)(params)](./kibana-plugin-plugins-expressions-public.execution._constructor_.md) |  | Constructs a new instance of the <code>Execution</code> class |
+|  [(constructor)(execution)](./kibana-plugin-plugins-expressions-public.execution._constructor_.md) |  | Constructs a new instance of the <code>Execution</code> class |
 
 ## Properties
 
 |  Property | Modifiers | Type | Description |
 |  --- | --- | --- | --- |
-|  [context](./kibana-plugin-plugins-expressions-public.execution.context.md) |  | <code>ExecutionContext&lt;Input, InspectorAdapters&gt; &amp; ExtraContext</code> | Execution context - object that allows to do side-effects. Context is passed to every function. |
-|  [contract](./kibana-plugin-plugins-expressions-public.execution.contract.md) |  | <code>ExecutionContract&lt;ExtraContext, Input, Output, InspectorAdapters&gt;</code> | Contract is a public representation of <code>Execution</code> instances. Contract we can return to other plugins for their consumption. |
+|  [context](./kibana-plugin-plugins-expressions-public.execution.context.md) |  | <code>ExecutionContext&lt;InspectorAdapters&gt;</code> | Execution context - object that allows to do side-effects. Context is passed to every function. |
+|  [contract](./kibana-plugin-plugins-expressions-public.execution.contract.md) |  | <code>ExecutionContract&lt;Input, Output, InspectorAdapters&gt;</code> | Contract is a public representation of <code>Execution</code> instances. Contract we can return to other plugins for their consumption. |
+|  [execution](./kibana-plugin-plugins-expressions-public.execution.execution.md) |  | <code>ExecutionParams</code> |  |
 |  [expression](./kibana-plugin-plugins-expressions-public.execution.expression.md) |  | <code>string</code> |  |
 |  [input](./kibana-plugin-plugins-expressions-public.execution.input.md) |  | <code>Input</code> | Initial input of the execution.<!-- -->N.B. It is initialized to <code>null</code> rather than <code>undefined</code> for legacy reasons, because in legacy interpreter it was set to <code>null</code> by default. |
 |  [inspectorAdapters](./kibana-plugin-plugins-expressions-public.execution.inspectoradapters.md) |  | <code>InspectorAdapters</code> |  |
-|  [params](./kibana-plugin-plugins-expressions-public.execution.params.md) |  | <code>ExecutionParams&lt;ExtraContext&gt;</code> |  |
 |  [result](./kibana-plugin-plugins-expressions-public.execution.result.md) |  | <code>Promise&lt;Output &#124; ExpressionValueError&gt;</code> |  |
 |  [state](./kibana-plugin-plugins-expressions-public.execution.state.md) |  | <code>ExecutionContainer&lt;Output &#124; ExpressionValueError&gt;</code> | Dynamic state of the execution. |
 
@@ -35,7 +35,7 @@ export declare class Execution<ExtraContext extends Record<string, unknown> = Re
 |  --- | --- | --- |
 |  [cancel()](./kibana-plugin-plugins-expressions-public.execution.cancel.md) |  | Stop execution of expression. |
 |  [cast(value, toTypeNames)](./kibana-plugin-plugins-expressions-public.execution.cast.md) |  |  |
-|  [interpret(ast, input, options)](./kibana-plugin-plugins-expressions-public.execution.interpret.md) |  |  |
+|  [interpret(ast, input)](./kibana-plugin-plugins-expressions-public.execution.interpret.md) |  |  |
 |  [invokeChain(chainArr, input)](./kibana-plugin-plugins-expressions-public.execution.invokechain.md) |  |  |
 |  [invokeFunction(fn, input, args)](./kibana-plugin-plugins-expressions-public.execution.invokefunction.md) |  |  |
 |  [resolveArgs(fnDef, input, argAsts)](./kibana-plugin-plugins-expressions-public.execution.resolveargs.md) |  |  |
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getinitialinput.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getsearchcontext.md
similarity index 55%
rename from docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getinitialinput.md
rename to docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getsearchcontext.md
index 460b1622c6fbd..471e18ee6a7eb 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getinitialinput.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getsearchcontext.md
@@ -1,13 +1,13 @@
 <!-- Do not edit this file. It is automatically generated by API Documenter. -->
 
-[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [ExecutionContext](./kibana-plugin-plugins-expressions-public.executioncontext.md) &gt; [getInitialInput](./kibana-plugin-plugins-expressions-public.executioncontext.getinitialinput.md)
+[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [ExecutionContext](./kibana-plugin-plugins-expressions-public.executioncontext.md) &gt; [getSearchContext](./kibana-plugin-plugins-expressions-public.executioncontext.getsearchcontext.md)
 
-## ExecutionContext.getInitialInput property
+## ExecutionContext.getSearchContext property
 
-Get initial input with which execution started.
+Get search context of the expression.
 
 <b>Signature:</b>
 
 ```typescript
-getInitialInput: () => Input;
+getSearchContext: () => ExecutionContextSearch;
 ```
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.search.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getsearchsessionid.md
similarity index 63%
rename from docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.search.md
rename to docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getsearchsessionid.md
index 05501a475cbd4..107ae16dc8901 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.search.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getsearchsessionid.md
@@ -1,13 +1,13 @@
 <!-- Do not edit this file. It is automatically generated by API Documenter. -->
 
-[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [ExecutionContext](./kibana-plugin-plugins-expressions-public.executioncontext.md) &gt; [search](./kibana-plugin-plugins-expressions-public.executioncontext.search.md)
+[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [ExecutionContext](./kibana-plugin-plugins-expressions-public.executioncontext.md) &gt; [getSearchSessionId](./kibana-plugin-plugins-expressions-public.executioncontext.getsearchsessionid.md)
 
-## ExecutionContext.search property
+## ExecutionContext.getSearchSessionId property
 
 Search context in which expression should operate.
 
 <b>Signature:</b>
 
 ```typescript
-search?: ExecutionContextSearch;
+getSearchSessionId: () => string | undefined;
 ```
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md
index 786e94455c600..2a1a78b8fcb1a 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md
@@ -9,7 +9,7 @@
 <b>Signature:</b>
 
 ```typescript
-export interface ExecutionContext<Input = unknown, InspectorAdapters extends Adapters = Adapters> 
+export interface ExecutionContext<InspectorAdapters extends Adapters = Adapters> 
 ```
 
 ## Properties
@@ -17,10 +17,10 @@ export interface ExecutionContext<Input = unknown, InspectorAdapters extends Ada
 |  Property | Type | Description |
 |  --- | --- | --- |
 |  [abortSignal](./kibana-plugin-plugins-expressions-public.executioncontext.abortsignal.md) | <code>AbortSignal</code> | Adds ability to abort current execution. |
-|  [getInitialInput](./kibana-plugin-plugins-expressions-public.executioncontext.getinitialinput.md) | <code>() =&gt; Input</code> | Get initial input with which execution started. |
 |  [getSavedObject](./kibana-plugin-plugins-expressions-public.executioncontext.getsavedobject.md) | <code>&lt;T extends SavedObjectAttributes = SavedObjectAttributes&gt;(type: string, id: string) =&gt; Promise&lt;SavedObject&lt;T&gt;&gt;</code> | Allows to fetch saved objects from ElasticSearch. In browser <code>getSavedObject</code> function is provided automatically by the Expressions plugin. On the server the caller of the expression has to provide this context function. The reason is because on the browser we always know the user who tries to fetch a saved object, thus saved object client is scoped automatically to that user. However, on the server we can scope that saved object client to any user, or even not scope it at all and execute it as an "internal" user. |
+|  [getSearchContext](./kibana-plugin-plugins-expressions-public.executioncontext.getsearchcontext.md) | <code>() =&gt; ExecutionContextSearch</code> | Get search context of the expression. |
+|  [getSearchSessionId](./kibana-plugin-plugins-expressions-public.executioncontext.getsearchsessionid.md) | <code>() =&gt; string &#124; undefined</code> | Search context in which expression should operate. |
 |  [inspectorAdapters](./kibana-plugin-plugins-expressions-public.executioncontext.inspectoradapters.md) | <code>InspectorAdapters</code> | Adapters for <code>inspector</code> plugin. |
-|  [search](./kibana-plugin-plugins-expressions-public.executioncontext.search.md) | <code>ExecutionContextSearch</code> | Search context in which expression should operate. |
 |  [types](./kibana-plugin-plugins-expressions-public.executioncontext.types.md) | <code>Record&lt;string, ExpressionType&gt;</code> | A map of available expression types. |
 |  [variables](./kibana-plugin-plugins-expressions-public.executioncontext.variables.md) | <code>Record&lt;string, unknown&gt;</code> | Context variables that can be consumed using <code>var</code> and <code>var_set</code> functions. |
 
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract._constructor_.md
index 89a99ef2f8ef8..ee8b113881a05 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract._constructor_.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract._constructor_.md
@@ -9,12 +9,12 @@ Constructs a new instance of the `ExecutionContract` class
 <b>Signature:</b>
 
 ```typescript
-constructor(execution: Execution<ExtraContext, Input, Output, InspectorAdapters>);
+constructor(execution: Execution<Input, Output, InspectorAdapters>);
 ```
 
 ## Parameters
 
 |  Parameter | Type | Description |
 |  --- | --- | --- |
-|  execution | <code>Execution&lt;ExtraContext, Input, Output, InspectorAdapters&gt;</code> |  |
+|  execution | <code>Execution&lt;Input, Output, InspectorAdapters&gt;</code> |  |
 
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.execution.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.execution.md
index f7911250488f2..aa058c71c12df 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.execution.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.execution.md
@@ -7,5 +7,5 @@
 <b>Signature:</b>
 
 ```typescript
-protected readonly execution: Execution<ExtraContext, Input, Output, InspectorAdapters>;
+protected readonly execution: Execution<Input, Output, InspectorAdapters>;
 ```
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.md
index d05620eace208..f2c050bbfe0ba 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.md
@@ -9,7 +9,7 @@
 <b>Signature:</b>
 
 ```typescript
-export declare class ExecutionContract<ExtraContext extends Record<string, unknown> = Record<string, unknown>, Input = unknown, Output = unknown, InspectorAdapters = unknown> 
+export declare class ExecutionContract<Input = unknown, Output = unknown, InspectorAdapters = unknown> 
 ```
 
 ## Constructors
@@ -23,7 +23,7 @@ export declare class ExecutionContract<ExtraContext extends Record<string, unkno
 |  Property | Modifiers | Type | Description |
 |  --- | --- | --- | --- |
 |  [cancel](./kibana-plugin-plugins-expressions-public.executioncontract.cancel.md) |  | <code>() =&gt; void</code> | Cancel the execution of the expression. This will set abort signal (available in execution context) to aborted state, letting expression functions to stop their execution. |
-|  [execution](./kibana-plugin-plugins-expressions-public.executioncontract.execution.md) |  | <code>Execution&lt;ExtraContext, Input, Output, InspectorAdapters&gt;</code> |  |
+|  [execution](./kibana-plugin-plugins-expressions-public.executioncontract.execution.md) |  | <code>Execution&lt;Input, Output, InspectorAdapters&gt;</code> |  |
 |  [getAst](./kibana-plugin-plugins-expressions-public.executioncontract.getast.md) |  | <code>() =&gt; ExpressionAstExpression</code> | Get AST used to execute the expression. |
 |  [getData](./kibana-plugin-plugins-expressions-public.executioncontract.getdata.md) |  | <code>() =&gt; Promise&lt;Output &#124; ExpressionValueError&gt;</code> | Returns the final output of expression, if any error happens still wraps that error into <code>ExpressionValueError</code> type and returns that. This function never throws. |
 |  [getExpression](./kibana-plugin-plugins-expressions-public.executioncontract.getexpression.md) |  | <code>() =&gt; string</code> | Get string representation of the expression. Returns the original string if execution was started from a string. If execution was started from an AST this method returns a string generated from AST. |
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.debug.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.debug.md
deleted file mode 100644
index 61ec72465f55e..0000000000000
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.debug.md
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- Do not edit this file. It is automatically generated by API Documenter. -->
-
-[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [ExecutionParams](./kibana-plugin-plugins-expressions-public.executionparams.md) &gt; [debug](./kibana-plugin-plugins-expressions-public.executionparams.debug.md)
-
-## ExecutionParams.debug property
-
-Whether to execute expression in \*debug mode\*. In \*debug mode\* inputs and outputs as well as all resolved arguments and time it took to execute each function are saved and are available for introspection.
-
-<b>Signature:</b>
-
-```typescript
-debug?: boolean;
-```
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.md
index e39dc231fbf96..6e5d70c61ead6 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.md
@@ -7,7 +7,7 @@
 <b>Signature:</b>
 
 ```typescript
-export interface ExecutionParams<ExtraContext extends Record<string, unknown> = Record<string, unknown>> 
+export interface ExecutionParams 
 ```
 
 ## Properties
@@ -15,8 +15,7 @@ export interface ExecutionParams<ExtraContext extends Record<string, unknown> =
 |  Property | Type | Description |
 |  --- | --- | --- |
 |  [ast](./kibana-plugin-plugins-expressions-public.executionparams.ast.md) | <code>ExpressionAstExpression</code> |  |
-|  [context](./kibana-plugin-plugins-expressions-public.executionparams.context.md) | <code>ExtraContext</code> |  |
-|  [debug](./kibana-plugin-plugins-expressions-public.executionparams.debug.md) | <code>boolean</code> | Whether to execute expression in \*debug mode\*. In \*debug mode\* inputs and outputs as well as all resolved arguments and time it took to execute each function are saved and are available for introspection. |
 |  [executor](./kibana-plugin-plugins-expressions-public.executionparams.executor.md) | <code>Executor&lt;any&gt;</code> |  |
 |  [expression](./kibana-plugin-plugins-expressions-public.executionparams.expression.md) | <code>string</code> |  |
+|  [params](./kibana-plugin-plugins-expressions-public.executionparams.params.md) | <code>ExpressionExecutionParams</code> |  |
 
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.context.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.params.md
similarity index 65%
rename from docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.context.md
rename to docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.params.md
index b6013162ef2ae..0dbe87bfda79e 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.context.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.params.md
@@ -1,11 +1,11 @@
 <!-- Do not edit this file. It is automatically generated by API Documenter. -->
 
-[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [ExecutionParams](./kibana-plugin-plugins-expressions-public.executionparams.md) &gt; [context](./kibana-plugin-plugins-expressions-public.executionparams.context.md)
+[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [ExecutionParams](./kibana-plugin-plugins-expressions-public.executionparams.md) &gt; [params](./kibana-plugin-plugins-expressions-public.executionparams.params.md)
 
-## ExecutionParams.context property
+## ExecutionParams.params property
 
 <b>Signature:</b>
 
 ```typescript
-context?: ExtraContext;
+params: ExpressionExecutionParams;
 ```
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.createexecution.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.createexecution.md
index e6765064d4a27..2832ba92262f2 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.createexecution.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.createexecution.md
@@ -7,7 +7,7 @@
 <b>Signature:</b>
 
 ```typescript
-createExecution<ExtraContext extends Record<string, unknown> = Record<string, unknown>, Input = unknown, Output = unknown>(ast: string | ExpressionAstExpression, context?: ExtraContext, { debug }?: ExpressionExecOptions): Execution<Context & ExtraContext, Input, Output>;
+createExecution<Input = unknown, Output = unknown>(ast: string | ExpressionAstExpression, params?: ExpressionExecutionParams): Execution<Input, Output>;
 ```
 
 ## Parameters
@@ -15,10 +15,9 @@ createExecution<ExtraContext extends Record<string, unknown> = Record<string, un
 |  Parameter | Type | Description |
 |  --- | --- | --- |
 |  ast | <code>string &#124; ExpressionAstExpression</code> |  |
-|  context | <code>ExtraContext</code> |  |
-|  { debug } | <code>ExpressionExecOptions</code> |  |
+|  params | <code>ExpressionExecutionParams</code> |  |
 
 <b>Returns:</b>
 
-`Execution<Context & ExtraContext, Input, Output>`
+`Execution<Input, Output>`
 
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.md
index 013624f30b45a..aefd04112dc1c 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.md
@@ -29,7 +29,7 @@ export declare class Executor<Context extends Record<string, unknown> = Record<s
 
 |  Method | Modifiers | Description |
 |  --- | --- | --- |
-|  [createExecution(ast, context, { debug })](./kibana-plugin-plugins-expressions-public.executor.createexecution.md) |  |  |
+|  [createExecution(ast, params)](./kibana-plugin-plugins-expressions-public.executor.createexecution.md) |  |  |
 |  [createWithDefaults(state)](./kibana-plugin-plugins-expressions-public.executor.createwithdefaults.md) | <code>static</code> |  |
 |  [extendContext(extraContext)](./kibana-plugin-plugins-expressions-public.executor.extendcontext.md) |  |  |
 |  [extract(ast)](./kibana-plugin-plugins-expressions-public.executor.extract.md) |  |  |
@@ -41,6 +41,6 @@ export declare class Executor<Context extends Record<string, unknown> = Record<s
 |  [inject(ast, references)](./kibana-plugin-plugins-expressions-public.executor.inject.md) |  |  |
 |  [registerFunction(functionDefinition)](./kibana-plugin-plugins-expressions-public.executor.registerfunction.md) |  |  |
 |  [registerType(typeDefinition)](./kibana-plugin-plugins-expressions-public.executor.registertype.md) |  |  |
-|  [run(ast, input, context, options)](./kibana-plugin-plugins-expressions-public.executor.run.md) |  | Execute expression and return result. |
+|  [run(ast, input, params)](./kibana-plugin-plugins-expressions-public.executor.run.md) |  | Execute expression and return result. |
 |  [telemetry(ast, telemetryData)](./kibana-plugin-plugins-expressions-public.executor.telemetry.md) |  |  |
 
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.run.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.run.md
index 0ebb3025a1c16..81fc8aa8658ca 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.run.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.run.md
@@ -9,7 +9,7 @@ Execute expression and return result.
 <b>Signature:</b>
 
 ```typescript
-run<Input, Output, ExtraContext extends Record<string, unknown> = Record<string, unknown>>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext, options?: ExpressionExecOptions): Promise<Output>;
+run<Input, Output>(ast: string | ExpressionAstExpression, input: Input, params?: ExpressionExecutionParams): Promise<Output>;
 ```
 
 ## Parameters
@@ -18,8 +18,7 @@ run<Input, Output, ExtraContext extends Record<string, unknown> = Record<string,
 |  --- | --- | --- |
 |  ast | <code>string &#124; ExpressionAstExpression</code> |  |
 |  input | <code>Input</code> |  |
-|  context | <code>ExtraContext</code> |  |
-|  options | <code>ExpressionExecOptions</code> |  |
+|  params | <code>ExpressionExecutionParams</code> |  |
 
 <b>Returns:</b>
 
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.execute.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.execute.md
index 18b856b946da4..043d3472228a2 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.execute.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.execute.md
@@ -9,5 +9,5 @@ Starts expression execution and immediately returns `ExecutionContract` instance
 <b>Signature:</b>
 
 ```typescript
-execute: <Input = unknown, Output = unknown, ExtraContext extends Record<string, unknown> = Record<string, unknown>>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext, options?: ExpressionExecOptions) => ExecutionContract<ExtraContext, Input, Output>;
+execute: <Input = unknown, Output = unknown>(ast: string | ExpressionAstExpression, input: Input, params?: ExpressionExecutionParams) => ExecutionContract<Input, Output>;
 ```
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.md
index def572abead22..6b678fc4fbc26 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.md
@@ -16,12 +16,12 @@ export interface ExpressionsServiceStart
 
 |  Property | Type | Description |
 |  --- | --- | --- |
-|  [execute](./kibana-plugin-plugins-expressions-public.expressionsservicestart.execute.md) | <code>&lt;Input = unknown, Output = unknown, ExtraContext extends Record&lt;string, unknown&gt; = Record&lt;string, unknown&gt;&gt;(ast: string &#124; ExpressionAstExpression, input: Input, context?: ExtraContext, options?: ExpressionExecOptions) =&gt; ExecutionContract&lt;ExtraContext, Input, Output&gt;</code> | Starts expression execution and immediately returns <code>ExecutionContract</code> instance that tracks the progress of the execution and can be used to interact with the execution. |
+|  [execute](./kibana-plugin-plugins-expressions-public.expressionsservicestart.execute.md) | <code>&lt;Input = unknown, Output = unknown&gt;(ast: string &#124; ExpressionAstExpression, input: Input, params?: ExpressionExecutionParams) =&gt; ExecutionContract&lt;Input, Output&gt;</code> | Starts expression execution and immediately returns <code>ExecutionContract</code> instance that tracks the progress of the execution and can be used to interact with the execution. |
 |  [fork](./kibana-plugin-plugins-expressions-public.expressionsservicestart.fork.md) | <code>() =&gt; ExpressionsService</code> | Create a new instance of <code>ExpressionsService</code>. The new instance inherits all state of the original <code>ExpressionsService</code>, including all expression types, expression functions and context. Also, all new types and functions registered in the original services AFTER the forking event will be available in the forked instance. However, all new types and functions registered in the forked instances will NOT be available to the original service. |
 |  [getFunction](./kibana-plugin-plugins-expressions-public.expressionsservicestart.getfunction.md) | <code>(name: string) =&gt; ReturnType&lt;Executor['getFunction']&gt;</code> | Get a registered <code>ExpressionFunction</code> by its name, which was registered using the <code>registerFunction</code> method. The returned <code>ExpressionFunction</code> instance is an internal representation of the function in Expressions service - do not mutate that object. |
 |  [getRenderer](./kibana-plugin-plugins-expressions-public.expressionsservicestart.getrenderer.md) | <code>(name: string) =&gt; ReturnType&lt;ExpressionRendererRegistry['get']&gt;</code> | Get a registered <code>ExpressionRenderer</code> by its name, which was registered using the <code>registerRenderer</code> method. The returned <code>ExpressionRenderer</code> instance is an internal representation of the renderer in Expressions service - do not mutate that object. |
 |  [getType](./kibana-plugin-plugins-expressions-public.expressionsservicestart.gettype.md) | <code>(name: string) =&gt; ReturnType&lt;Executor['getType']&gt;</code> | Get a registered <code>ExpressionType</code> by its name, which was registered using the <code>registerType</code> method. The returned <code>ExpressionType</code> instance is an internal representation of the type in Expressions service - do not mutate that object. |
-|  [run](./kibana-plugin-plugins-expressions-public.expressionsservicestart.run.md) | <code>&lt;Input, Output, ExtraContext extends Record&lt;string, unknown&gt; = Record&lt;string, unknown&gt;&gt;(ast: string &#124; ExpressionAstExpression, input: Input, context?: ExtraContext, options?: ExpressionExecOptions) =&gt; Promise&lt;Output&gt;</code> | Executes expression string or a parsed expression AST and immediately returns the result.<!-- -->Below example will execute <code>sleep 100 &#124; clog</code> expression with <code>123</code> initial input to the first function.
+|  [run](./kibana-plugin-plugins-expressions-public.expressionsservicestart.run.md) | <code>&lt;Input, Output&gt;(ast: string &#124; ExpressionAstExpression, input: Input, params?: ExpressionExecutionParams) =&gt; Promise&lt;Output&gt;</code> | Executes expression string or a parsed expression AST and immediately returns the result.<!-- -->Below example will execute <code>sleep 100 &#124; clog</code> expression with <code>123</code> initial input to the first function.
 ```ts
 expressions.run('sleep 100 | clog', 123);
 
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.run.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.run.md
index d717af51a00fa..9efca0011174c 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.run.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.run.md
@@ -24,5 +24,5 @@ expressions.run('...', null, { elasticsearchClient });
 <b>Signature:</b>
 
 ```typescript
-run: <Input, Output, ExtraContext extends Record<string, unknown> = Record<string, unknown>>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext, options?: ExpressionExecOptions) => Promise<Output>;
+run: <Input, Output>(ast: string | ExpressionAstExpression, input: Input, params?: ExpressionExecutionParams) => Promise<Output>;
 ```
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md
index d6e02350bae3f..e2ad6215e25d0 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md
@@ -22,6 +22,7 @@ export interface IExpressionLoaderParams
 |  [inspectorAdapters](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.inspectoradapters.md) | <code>Adapters</code> |  |
 |  [onRenderError](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.onrendererror.md) | <code>RenderErrorHandlerFnType</code> |  |
 |  [searchContext](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md) | <code>ExecutionContextSearch</code> |  |
+|  [searchSessionId](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchsessionid.md) | <code>string</code> |  |
 |  [uiState](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.uistate.md) | <code>unknown</code> |  |
 |  [variables](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.variables.md) | <code>Record&lt;string, any&gt;</code> |  |
 
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchsessionid.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchsessionid.md
new file mode 100644
index 0000000000000..bb021b003f0d3
--- /dev/null
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchsessionid.md
@@ -0,0 +1,11 @@
+<!-- Do not edit this file. It is automatically generated by API Documenter. -->
+
+[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) &gt; [searchSessionId](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchsessionid.md)
+
+## IExpressionLoaderParams.searchSessionId property
+
+<b>Signature:</b>
+
+```typescript
+searchSessionId?: string;
+```
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution._constructor_.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution._constructor_.md
index 75f4cc4c2a017..f24aae8603b7d 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution._constructor_.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution._constructor_.md
@@ -9,12 +9,12 @@ Constructs a new instance of the `Execution` class
 <b>Signature:</b>
 
 ```typescript
-constructor(params: ExecutionParams<ExtraContext>);
+constructor(execution: ExecutionParams);
 ```
 
 ## Parameters
 
 |  Parameter | Type | Description |
 |  --- | --- | --- |
-|  params | <code>ExecutionParams&lt;ExtraContext&gt;</code> |  |
+|  execution | <code>ExecutionParams</code> |  |
 
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.context.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.context.md
index d1969fb0859b7..65c7bdca0fe5d 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.context.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.context.md
@@ -9,5 +9,5 @@ Execution context - object that allows to do side-effects. Context is passed to
 <b>Signature:</b>
 
 ```typescript
-readonly context: ExecutionContext<Input, InspectorAdapters> & ExtraContext;
+readonly context: ExecutionContext<InspectorAdapters>;
 ```
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.contract.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.contract.md
index 149b5a7ced9cb..2fc6a38997f77 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.contract.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.contract.md
@@ -9,5 +9,5 @@ Contract is a public representation of `Execution` instances. Contract we can re
 <b>Signature:</b>
 
 ```typescript
-readonly contract: ExecutionContract<ExtraContext, Input, Output, InspectorAdapters>;
+readonly contract: ExecutionContract<Input, Output, InspectorAdapters>;
 ```
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.params.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.execution.md
similarity index 67%
rename from docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.params.md
rename to docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.execution.md
index 498f9bbfccfa4..acaccdeab7321 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.params.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.execution.md
@@ -1,11 +1,11 @@
 <!-- Do not edit this file. It is automatically generated by API Documenter. -->
 
-[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) &gt; [Execution](./kibana-plugin-plugins-expressions-server.execution.md) &gt; [params](./kibana-plugin-plugins-expressions-server.execution.params.md)
+[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) &gt; [Execution](./kibana-plugin-plugins-expressions-server.execution.md) &gt; [execution](./kibana-plugin-plugins-expressions-server.execution.execution.md)
 
-## Execution.params property
+## Execution.execution property
 
 <b>Signature:</b>
 
 ```typescript
-readonly params: ExecutionParams<ExtraContext>;
+readonly execution: ExecutionParams;
 ```
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.interpret.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.interpret.md
index cf59e796e6120..e425bdc70e349 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.interpret.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.interpret.md
@@ -7,7 +7,7 @@
 <b>Signature:</b>
 
 ```typescript
-interpret<T>(ast: ExpressionAstNode, input: T, options?: ExpressionExecOptions): Promise<unknown>;
+interpret<T>(ast: ExpressionAstNode, input: T): Promise<unknown>;
 ```
 
 ## Parameters
@@ -16,7 +16,6 @@ interpret<T>(ast: ExpressionAstNode, input: T, options?: ExpressionExecOptions):
 |  --- | --- | --- |
 |  ast | <code>ExpressionAstNode</code> |  |
 |  input | <code>T</code> |  |
-|  options | <code>ExpressionExecOptions</code> |  |
 
 <b>Returns:</b>
 
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.md
index fc663dd115580..c94ae9bcfe946 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.md
@@ -7,25 +7,25 @@
 <b>Signature:</b>
 
 ```typescript
-export declare class Execution<ExtraContext extends Record<string, unknown> = Record<string, unknown>, Input = unknown, Output = unknown, InspectorAdapters extends Adapters = ExtraContext['inspectorAdapters'] extends object ? ExtraContext['inspectorAdapters'] : DefaultInspectorAdapters> 
+export declare class Execution<Input = unknown, Output = unknown, InspectorAdapters extends Adapters = ExpressionExecutionParams['inspectorAdapters'] extends object ? ExpressionExecutionParams['inspectorAdapters'] : DefaultInspectorAdapters> 
 ```
 
 ## Constructors
 
 |  Constructor | Modifiers | Description |
 |  --- | --- | --- |
-|  [(constructor)(params)](./kibana-plugin-plugins-expressions-server.execution._constructor_.md) |  | Constructs a new instance of the <code>Execution</code> class |
+|  [(constructor)(execution)](./kibana-plugin-plugins-expressions-server.execution._constructor_.md) |  | Constructs a new instance of the <code>Execution</code> class |
 
 ## Properties
 
 |  Property | Modifiers | Type | Description |
 |  --- | --- | --- | --- |
-|  [context](./kibana-plugin-plugins-expressions-server.execution.context.md) |  | <code>ExecutionContext&lt;Input, InspectorAdapters&gt; &amp; ExtraContext</code> | Execution context - object that allows to do side-effects. Context is passed to every function. |
-|  [contract](./kibana-plugin-plugins-expressions-server.execution.contract.md) |  | <code>ExecutionContract&lt;ExtraContext, Input, Output, InspectorAdapters&gt;</code> | Contract is a public representation of <code>Execution</code> instances. Contract we can return to other plugins for their consumption. |
+|  [context](./kibana-plugin-plugins-expressions-server.execution.context.md) |  | <code>ExecutionContext&lt;InspectorAdapters&gt;</code> | Execution context - object that allows to do side-effects. Context is passed to every function. |
+|  [contract](./kibana-plugin-plugins-expressions-server.execution.contract.md) |  | <code>ExecutionContract&lt;Input, Output, InspectorAdapters&gt;</code> | Contract is a public representation of <code>Execution</code> instances. Contract we can return to other plugins for their consumption. |
+|  [execution](./kibana-plugin-plugins-expressions-server.execution.execution.md) |  | <code>ExecutionParams</code> |  |
 |  [expression](./kibana-plugin-plugins-expressions-server.execution.expression.md) |  | <code>string</code> |  |
 |  [input](./kibana-plugin-plugins-expressions-server.execution.input.md) |  | <code>Input</code> | Initial input of the execution.<!-- -->N.B. It is initialized to <code>null</code> rather than <code>undefined</code> for legacy reasons, because in legacy interpreter it was set to <code>null</code> by default. |
 |  [inspectorAdapters](./kibana-plugin-plugins-expressions-server.execution.inspectoradapters.md) |  | <code>InspectorAdapters</code> |  |
-|  [params](./kibana-plugin-plugins-expressions-server.execution.params.md) |  | <code>ExecutionParams&lt;ExtraContext&gt;</code> |  |
 |  [result](./kibana-plugin-plugins-expressions-server.execution.result.md) |  | <code>Promise&lt;Output &#124; ExpressionValueError&gt;</code> |  |
 |  [state](./kibana-plugin-plugins-expressions-server.execution.state.md) |  | <code>ExecutionContainer&lt;Output &#124; ExpressionValueError&gt;</code> | Dynamic state of the execution. |
 
@@ -35,7 +35,7 @@ export declare class Execution<ExtraContext extends Record<string, unknown> = Re
 |  --- | --- | --- |
 |  [cancel()](./kibana-plugin-plugins-expressions-server.execution.cancel.md) |  | Stop execution of expression. |
 |  [cast(value, toTypeNames)](./kibana-plugin-plugins-expressions-server.execution.cast.md) |  |  |
-|  [interpret(ast, input, options)](./kibana-plugin-plugins-expressions-server.execution.interpret.md) |  |  |
+|  [interpret(ast, input)](./kibana-plugin-plugins-expressions-server.execution.interpret.md) |  |  |
 |  [invokeChain(chainArr, input)](./kibana-plugin-plugins-expressions-server.execution.invokechain.md) |  |  |
 |  [invokeFunction(fn, input, args)](./kibana-plugin-plugins-expressions-server.execution.invokefunction.md) |  |  |
 |  [resolveArgs(fnDef, input, argAsts)](./kibana-plugin-plugins-expressions-server.execution.resolveargs.md) |  |  |
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getinitialinput.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getsearchcontext.md
similarity index 55%
rename from docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getinitialinput.md
rename to docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getsearchcontext.md
index b5f9b91e1c7b7..783841fbafa92 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getinitialinput.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getsearchcontext.md
@@ -1,13 +1,13 @@
 <!-- Do not edit this file. It is automatically generated by API Documenter. -->
 
-[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) &gt; [ExecutionContext](./kibana-plugin-plugins-expressions-server.executioncontext.md) &gt; [getInitialInput](./kibana-plugin-plugins-expressions-server.executioncontext.getinitialinput.md)
+[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) &gt; [ExecutionContext](./kibana-plugin-plugins-expressions-server.executioncontext.md) &gt; [getSearchContext](./kibana-plugin-plugins-expressions-server.executioncontext.getsearchcontext.md)
 
-## ExecutionContext.getInitialInput property
+## ExecutionContext.getSearchContext property
 
-Get initial input with which execution started.
+Get search context of the expression.
 
 <b>Signature:</b>
 
 ```typescript
-getInitialInput: () => Input;
+getSearchContext: () => ExecutionContextSearch;
 ```
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.search.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getsearchsessionid.md
similarity index 63%
rename from docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.search.md
rename to docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getsearchsessionid.md
index 641e50696f6e0..a69f0ed32bd51 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.search.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getsearchsessionid.md
@@ -1,13 +1,13 @@
 <!-- Do not edit this file. It is automatically generated by API Documenter. -->
 
-[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) &gt; [ExecutionContext](./kibana-plugin-plugins-expressions-server.executioncontext.md) &gt; [search](./kibana-plugin-plugins-expressions-server.executioncontext.search.md)
+[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) &gt; [ExecutionContext](./kibana-plugin-plugins-expressions-server.executioncontext.md) &gt; [getSearchSessionId](./kibana-plugin-plugins-expressions-server.executioncontext.getsearchsessionid.md)
 
-## ExecutionContext.search property
+## ExecutionContext.getSearchSessionId property
 
 Search context in which expression should operate.
 
 <b>Signature:</b>
 
 ```typescript
-search?: ExecutionContextSearch;
+getSearchSessionId: () => string | undefined;
 ```
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md
index 0128ba934da73..047879fd99255 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md
@@ -9,7 +9,7 @@
 <b>Signature:</b>
 
 ```typescript
-export interface ExecutionContext<Input = unknown, InspectorAdapters extends Adapters = Adapters> 
+export interface ExecutionContext<InspectorAdapters extends Adapters = Adapters> 
 ```
 
 ## Properties
@@ -17,10 +17,10 @@ export interface ExecutionContext<Input = unknown, InspectorAdapters extends Ada
 |  Property | Type | Description |
 |  --- | --- | --- |
 |  [abortSignal](./kibana-plugin-plugins-expressions-server.executioncontext.abortsignal.md) | <code>AbortSignal</code> | Adds ability to abort current execution. |
-|  [getInitialInput](./kibana-plugin-plugins-expressions-server.executioncontext.getinitialinput.md) | <code>() =&gt; Input</code> | Get initial input with which execution started. |
 |  [getSavedObject](./kibana-plugin-plugins-expressions-server.executioncontext.getsavedobject.md) | <code>&lt;T extends SavedObjectAttributes = SavedObjectAttributes&gt;(type: string, id: string) =&gt; Promise&lt;SavedObject&lt;T&gt;&gt;</code> | Allows to fetch saved objects from ElasticSearch. In browser <code>getSavedObject</code> function is provided automatically by the Expressions plugin. On the server the caller of the expression has to provide this context function. The reason is because on the browser we always know the user who tries to fetch a saved object, thus saved object client is scoped automatically to that user. However, on the server we can scope that saved object client to any user, or even not scope it at all and execute it as an "internal" user. |
+|  [getSearchContext](./kibana-plugin-plugins-expressions-server.executioncontext.getsearchcontext.md) | <code>() =&gt; ExecutionContextSearch</code> | Get search context of the expression. |
+|  [getSearchSessionId](./kibana-plugin-plugins-expressions-server.executioncontext.getsearchsessionid.md) | <code>() =&gt; string &#124; undefined</code> | Search context in which expression should operate. |
 |  [inspectorAdapters](./kibana-plugin-plugins-expressions-server.executioncontext.inspectoradapters.md) | <code>InspectorAdapters</code> | Adapters for <code>inspector</code> plugin. |
-|  [search](./kibana-plugin-plugins-expressions-server.executioncontext.search.md) | <code>ExecutionContextSearch</code> | Search context in which expression should operate. |
 |  [types](./kibana-plugin-plugins-expressions-server.executioncontext.types.md) | <code>Record&lt;string, ExpressionType&gt;</code> | A map of available expression types. |
 |  [variables](./kibana-plugin-plugins-expressions-server.executioncontext.variables.md) | <code>Record&lt;string, unknown&gt;</code> | Context variables that can be consumed using <code>var</code> and <code>var_set</code> functions. |
 
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.debug.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.debug.md
deleted file mode 100644
index b3631e0aeebe6..0000000000000
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.debug.md
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- Do not edit this file. It is automatically generated by API Documenter. -->
-
-[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) &gt; [ExecutionParams](./kibana-plugin-plugins-expressions-server.executionparams.md) &gt; [debug](./kibana-plugin-plugins-expressions-server.executionparams.debug.md)
-
-## ExecutionParams.debug property
-
-Whether to execute expression in \*debug mode\*. In \*debug mode\* inputs and outputs as well as all resolved arguments and time it took to execute each function are saved and are available for introspection.
-
-<b>Signature:</b>
-
-```typescript
-debug?: boolean;
-```
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.md
index a7594bff48c1a..6a901c91ffff1 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.md
@@ -7,7 +7,7 @@
 <b>Signature:</b>
 
 ```typescript
-export interface ExecutionParams<ExtraContext extends Record<string, unknown> = Record<string, unknown>> 
+export interface ExecutionParams 
 ```
 
 ## Properties
@@ -15,8 +15,7 @@ export interface ExecutionParams<ExtraContext extends Record<string, unknown> =
 |  Property | Type | Description |
 |  --- | --- | --- |
 |  [ast](./kibana-plugin-plugins-expressions-server.executionparams.ast.md) | <code>ExpressionAstExpression</code> |  |
-|  [context](./kibana-plugin-plugins-expressions-server.executionparams.context.md) | <code>ExtraContext</code> |  |
-|  [debug](./kibana-plugin-plugins-expressions-server.executionparams.debug.md) | <code>boolean</code> | Whether to execute expression in \*debug mode\*. In \*debug mode\* inputs and outputs as well as all resolved arguments and time it took to execute each function are saved and are available for introspection. |
 |  [executor](./kibana-plugin-plugins-expressions-server.executionparams.executor.md) | <code>Executor&lt;any&gt;</code> |  |
 |  [expression](./kibana-plugin-plugins-expressions-server.executionparams.expression.md) | <code>string</code> |  |
+|  [params](./kibana-plugin-plugins-expressions-server.executionparams.params.md) | <code>ExpressionExecutionParams</code> |  |
 
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.context.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.params.md
similarity index 65%
rename from docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.context.md
rename to docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.params.md
index 8b9a210416dd6..fec60af33e0c4 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.context.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.params.md
@@ -1,11 +1,11 @@
 <!-- Do not edit this file. It is automatically generated by API Documenter. -->
 
-[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) &gt; [ExecutionParams](./kibana-plugin-plugins-expressions-server.executionparams.md) &gt; [context](./kibana-plugin-plugins-expressions-server.executionparams.context.md)
+[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) &gt; [ExecutionParams](./kibana-plugin-plugins-expressions-server.executionparams.md) &gt; [params](./kibana-plugin-plugins-expressions-server.executionparams.params.md)
 
-## ExecutionParams.context property
+## ExecutionParams.params property
 
 <b>Signature:</b>
 
 ```typescript
-context?: ExtraContext;
+params: ExpressionExecutionParams;
 ```
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.createexecution.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.createexecution.md
index 8ed228d70ff37..34e920a04fd02 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.createexecution.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.createexecution.md
@@ -7,7 +7,7 @@
 <b>Signature:</b>
 
 ```typescript
-createExecution<ExtraContext extends Record<string, unknown> = Record<string, unknown>, Input = unknown, Output = unknown>(ast: string | ExpressionAstExpression, context?: ExtraContext, { debug }?: ExpressionExecOptions): Execution<Context & ExtraContext, Input, Output>;
+createExecution<Input = unknown, Output = unknown>(ast: string | ExpressionAstExpression, params?: ExpressionExecutionParams): Execution<Input, Output>;
 ```
 
 ## Parameters
@@ -15,10 +15,9 @@ createExecution<ExtraContext extends Record<string, unknown> = Record<string, un
 |  Parameter | Type | Description |
 |  --- | --- | --- |
 |  ast | <code>string &#124; ExpressionAstExpression</code> |  |
-|  context | <code>ExtraContext</code> |  |
-|  { debug } | <code>ExpressionExecOptions</code> |  |
+|  params | <code>ExpressionExecutionParams</code> |  |
 
 <b>Returns:</b>
 
-`Execution<Context & ExtraContext, Input, Output>`
+`Execution<Input, Output>`
 
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.md
index 46ad60ae07126..97bb3ac895084 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.md
@@ -29,7 +29,7 @@ export declare class Executor<Context extends Record<string, unknown> = Record<s
 
 |  Method | Modifiers | Description |
 |  --- | --- | --- |
-|  [createExecution(ast, context, { debug })](./kibana-plugin-plugins-expressions-server.executor.createexecution.md) |  |  |
+|  [createExecution(ast, params)](./kibana-plugin-plugins-expressions-server.executor.createexecution.md) |  |  |
 |  [createWithDefaults(state)](./kibana-plugin-plugins-expressions-server.executor.createwithdefaults.md) | <code>static</code> |  |
 |  [extendContext(extraContext)](./kibana-plugin-plugins-expressions-server.executor.extendcontext.md) |  |  |
 |  [extract(ast)](./kibana-plugin-plugins-expressions-server.executor.extract.md) |  |  |
@@ -41,6 +41,6 @@ export declare class Executor<Context extends Record<string, unknown> = Record<s
 |  [inject(ast, references)](./kibana-plugin-plugins-expressions-server.executor.inject.md) |  |  |
 |  [registerFunction(functionDefinition)](./kibana-plugin-plugins-expressions-server.executor.registerfunction.md) |  |  |
 |  [registerType(typeDefinition)](./kibana-plugin-plugins-expressions-server.executor.registertype.md) |  |  |
-|  [run(ast, input, context, options)](./kibana-plugin-plugins-expressions-server.executor.run.md) |  | Execute expression and return result. |
+|  [run(ast, input, params)](./kibana-plugin-plugins-expressions-server.executor.run.md) |  | Execute expression and return result. |
 |  [telemetry(ast, telemetryData)](./kibana-plugin-plugins-expressions-server.executor.telemetry.md) |  |  |
 
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.run.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.run.md
index 879a4fb4056d2..de5ce1ed37f12 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.run.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.run.md
@@ -9,7 +9,7 @@ Execute expression and return result.
 <b>Signature:</b>
 
 ```typescript
-run<Input, Output, ExtraContext extends Record<string, unknown> = Record<string, unknown>>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext, options?: ExpressionExecOptions): Promise<Output>;
+run<Input, Output>(ast: string | ExpressionAstExpression, input: Input, params?: ExpressionExecutionParams): Promise<Output>;
 ```
 
 ## Parameters
@@ -18,8 +18,7 @@ run<Input, Output, ExtraContext extends Record<string, unknown> = Record<string,
 |  --- | --- | --- |
 |  ast | <code>string &#124; ExpressionAstExpression</code> |  |
 |  input | <code>Input</code> |  |
-|  context | <code>ExtraContext</code> |  |
-|  options | <code>ExpressionExecOptions</code> |  |
+|  params | <code>ExpressionExecutionParams</code> |  |
 
 <b>Returns:</b>
 
diff --git a/package.json b/package.json
index 84e9c0e2762eb..3a2d13fd5ef3b 100644
--- a/package.json
+++ b/package.json
@@ -228,7 +228,7 @@
     "@babel/register": "^7.10.5",
     "@babel/types": "^7.11.0",
     "@elastic/apm-rum": "^5.6.1",
-    "@elastic/charts": "23.2.1",
+    "@elastic/charts": "24.0.0",
     "@elastic/ems-client": "7.10.0",
     "@elastic/eslint-config-kibana": "0.15.0",
     "@elastic/eslint-plugin-eui": "0.0.2",
diff --git a/packages/kbn-apm-config-loader/src/config.test.ts b/packages/kbn-apm-config-loader/src/config.test.ts
index 83438215716ac..8adc4d84635af 100644
--- a/packages/kbn-apm-config-loader/src/config.test.ts
+++ b/packages/kbn-apm-config-loader/src/config.test.ts
@@ -28,6 +28,8 @@ import {
 
 import { ApmConfiguration } from './config';
 
+const initialEnv = { ...process.env };
+
 describe('ApmConfiguration', () => {
   beforeEach(() => {
     packageMock.raw = {
@@ -39,6 +41,7 @@ describe('ApmConfiguration', () => {
   });
 
   afterEach(() => {
+    process.env = { ...initialEnv };
     resetAllMocks();
   });
 
@@ -90,13 +93,16 @@ describe('ApmConfiguration', () => {
     let config = new ApmConfiguration(mockedRootDir, {}, false);
     expect(config.getConfig('serviceName')).toEqual(
       expect.objectContaining({
-        serverUrl: expect.any(String),
-        secretToken: expect.any(String),
+        breakdownMetrics: true,
       })
     );
 
     config = new ApmConfiguration(mockedRootDir, {}, true);
-    expect(Object.keys(config.getConfig('serviceName'))).not.toContain('serverUrl');
+    expect(config.getConfig('serviceName')).toEqual(
+      expect.objectContaining({
+        breakdownMetrics: false,
+      })
+    );
   });
 
   it('loads the configuration from the kibana config file', () => {
@@ -156,4 +162,32 @@ describe('ApmConfiguration', () => {
       })
     );
   });
+
+  it('correctly sets environment', () => {
+    delete process.env.ELASTIC_APM_ENVIRONMENT;
+    delete process.env.NODE_ENV;
+
+    let config = new ApmConfiguration(mockedRootDir, {}, false);
+    expect(config.getConfig('serviceName')).toEqual(
+      expect.objectContaining({
+        environment: 'development',
+      })
+    );
+
+    process.env.NODE_ENV = 'production';
+    config = new ApmConfiguration(mockedRootDir, {}, false);
+    expect(config.getConfig('serviceName')).toEqual(
+      expect.objectContaining({
+        environment: 'production',
+      })
+    );
+
+    process.env.ELASTIC_APM_ENVIRONMENT = 'ci';
+    config = new ApmConfiguration(mockedRootDir, {}, false);
+    expect(config.getConfig('serviceName')).toEqual(
+      expect.objectContaining({
+        environment: 'ci',
+      })
+    );
+  });
 });
diff --git a/packages/kbn-apm-config-loader/src/config.ts b/packages/kbn-apm-config-loader/src/config.ts
index 897e7fd7ca610..a611e205ec83a 100644
--- a/packages/kbn-apm-config-loader/src/config.ts
+++ b/packages/kbn-apm-config-loader/src/config.ts
@@ -26,32 +26,26 @@ import { readFileSync } from 'fs';
 import { ApmAgentConfig } from './types';
 
 const getDefaultConfig = (isDistributable: boolean): ApmAgentConfig => {
-  if (isDistributable) {
-    return {
-      active: false,
-      globalLabels: {},
-      // Do not use a centralized controlled config
-      centralConfig: false,
-      // Capture all exceptions that are not caught
-      logUncaughtExceptions: true,
-      // Can be performance intensive, disabling by default
-      breakdownMetrics: false,
-    };
-  }
-
+  // https://www.elastic.co/guide/en/apm/agent/nodejs/current/configuration.html
   return {
-    active: false,
-    serverUrl: 'https://f1542b814f674090afd914960583265f.apm.us-central1.gcp.cloud.es.io:443',
+    active: process.env.ELASTIC_APM_ACTIVE || false,
+    environment: process.env.ELASTIC_APM_ENVIRONMENT || process.env.NODE_ENV || 'development',
+
+    serverUrl: 'https://b1e3b4b4233e44cdad468c127d0af8d8.apm.europe-west1.gcp.cloud.es.io:443',
+
     // The secretToken below is intended to be hardcoded in this file even though
     // it makes it public. This is not a security/privacy issue. Normally we'd
     // instead disable the need for a secretToken in the APM Server config where
     // the data is transmitted to, but due to how it's being hosted, it's easier,
     // for now, to simply leave it in.
-    secretToken: 'R0Gjg46pE9K9wGestd',
+    secretToken: '2OyjjaI6RVkzx2O5CV',
+
+    logUncaughtExceptions: true,
     globalLabels: {},
-    breakdownMetrics: true,
     centralConfig: false,
-    logUncaughtExceptions: true,
+
+    // Can be performance intensive, disabling by default
+    breakdownMetrics: isDistributable ? false : true,
   };
 };
 
@@ -84,7 +78,8 @@ export class ApmConfiguration {
         getDefaultConfig(this.isDistributable),
         this.getConfigFromKibanaConfig(),
         this.getDevConfig(),
-        this.getDistConfig()
+        this.getDistConfig(),
+        this.getCIConfig()
       );
 
       const rev = this.getGitRev();
@@ -146,6 +141,21 @@ export class ApmConfiguration {
     };
   }
 
+  private getCIConfig(): ApmAgentConfig {
+    if (process.env.ELASTIC_APM_ENVIRONMENT !== 'ci') {
+      return {};
+    }
+
+    return {
+      globalLabels: {
+        branch: process.env.ghprbSourceBranch || '',
+        targetBranch: process.env.ghprbTargetBranch || '',
+        ciJobName: process.env.JOB_NAME || '',
+        ciBuildNumber: process.env.BUILD_NUMBER || '',
+      },
+    };
+  }
+
   private getGitRev() {
     if (this.isDistributable) {
       return this.pkgBuild.sha;
diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml
index fd0be15affab3..c660d37222504 100644
--- a/packages/kbn-optimizer/limits.yml
+++ b/packages/kbn-optimizer/limits.yml
@@ -14,7 +14,7 @@ pageLoadAssetSize:
   dashboard: 374194
   dashboardEnhanced: 65646
   dashboardMode: 22716
-  data: 1170713
+  data: 1287839
   dataEnhanced: 50420
   devTools: 38637
   discover: 105145
diff --git a/packages/kbn-optimizer/src/cli.ts b/packages/kbn-optimizer/src/cli.ts
index 28b3e37380b4e..976ffe1f5b1b5 100644
--- a/packages/kbn-optimizer/src/cli.ts
+++ b/packages/kbn-optimizer/src/cli.ts
@@ -146,7 +146,11 @@ run(
     await lastValueFrom(update$.pipe(logOptimizerState(log, config)));
 
     if (updateLimits) {
-      updateBundleLimits(log, config);
+      updateBundleLimits({
+        log,
+        config,
+        dropMissing: !(focus || filter),
+      });
     }
   },
   {
diff --git a/packages/kbn-optimizer/src/limits.ts b/packages/kbn-optimizer/src/limits.ts
index b0fae0901251d..64ec92657fc5b 100644
--- a/packages/kbn-optimizer/src/limits.ts
+++ b/packages/kbn-optimizer/src/limits.ts
@@ -79,10 +79,18 @@ export function validateLimitsForAllBundles(log: ToolingLog, config: OptimizerCo
   log.success('limits.yml file valid');
 }
 
-export function updateBundleLimits(log: ToolingLog, config: OptimizerConfig) {
+interface UpdateBundleLimitsOptions {
+  log: ToolingLog;
+  config: OptimizerConfig;
+  dropMissing: boolean;
+}
+
+export function updateBundleLimits({ log, config, dropMissing }: UpdateBundleLimitsOptions) {
   const metrics = getMetrics(log, config);
 
-  const pageLoadAssetSize: NonNullable<Limits['pageLoadAssetSize']> = {};
+  const pageLoadAssetSize: NonNullable<Limits['pageLoadAssetSize']> = dropMissing
+    ? {}
+    : config.limits.pageLoadAssetSize ?? {};
 
   for (const metric of metrics.sort((a, b) => a.id.localeCompare(b.id))) {
     if (metric.group === 'page load bundle size') {
diff --git a/packages/kbn-plugin-generator/README.md b/packages/kbn-plugin-generator/README.md
index 9ff9a8aa95ca2..bee8e6c2ca783 100644
--- a/packages/kbn-plugin-generator/README.md
+++ b/packages/kbn-plugin-generator/README.md
@@ -51,7 +51,7 @@ yarn kbn bootstrap
 
 Generated plugins receive a handful of scripts that can be used during development. Those scripts are detailed in the [README.md](template/README.md) file in each newly generated plugin, and expose the scripts provided by the [Kibana plugin helpers](../kbn-plugin-helpers), but here is a quick reference in case you need it:
 
-> ***NOTE:*** All of these scripts should be run from the generated plugin.
+> ***NOTE:*** The following scripts should be run from the generated plugin.
 
   - `yarn kbn bootstrap`
 
@@ -59,14 +59,6 @@ Generated plugins receive a handful of scripts that can be used during developme
 
     > ***IMPORTANT:*** Use this script instead of `yarn` to install dependencies when switching branches, and re-run it whenever your dependencies change.
 
-  - `yarn start`
-
-    Start kibana and have it include this plugin. You can pass any arguments that you would normally send to `bin/kibana`
-
-      ```
-      yarn start --elasticsearch.hosts http://localhost:9220
-      ```
-
   - `yarn build`
 
     Build a distributable archive of your plugin.
@@ -75,4 +67,15 @@ Generated plugins receive a handful of scripts that can be used during developme
 
     Run the server tests using mocha.
 
+
+To start kibana run the following command from Kibana root.
+
+  - `yarn start`
+
+    Start kibana and it will automatically include this plugin. You can pass any arguments that you would normally send to `bin/kibana`
+
+      ```
+      yarn start --elasticsearch.hosts http://localhost:9220
+      ```
+
 For more information about any of these commands run `yarn ${task} --help`. For a full list of tasks run `yarn run` or take a look in the `package.json` file.
diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json
index 980d9d02317b6..b1b5d6e2b419e 100644
--- a/packages/kbn-ui-shared-deps/package.json
+++ b/packages/kbn-ui-shared-deps/package.json
@@ -9,7 +9,7 @@
     "kbn:watch": "node scripts/build --dev --watch"
   },
   "dependencies": {
-    "@elastic/charts": "23.2.1",
+    "@elastic/charts": "24.0.0",
     "@elastic/eui": "29.5.0",
     "@elastic/numeral": "^2.5.0",
     "@kbn/i18n": "1.0.0",
diff --git a/src/core/server/elasticsearch/client/client_config.test.ts b/src/core/server/elasticsearch/client/client_config.test.ts
index e8083836d3c1e..2beb07e6da5bc 100644
--- a/src/core/server/elasticsearch/client/client_config.test.ts
+++ b/src/core/server/elasticsearch/client/client_config.test.ts
@@ -216,28 +216,14 @@ describe('parseClientOptions', () => {
         );
       });
 
-      it('adds auth to the nodes if both `username` and `password` are set', () => {
-        let options = parseClientOptions(
+      it('does not add auth to the nodes', () => {
+        const options = parseClientOptions(
           createConfig({
             username: 'user',
-            hosts: ['http://node-A:9200'],
-          }),
-          false
-        );
-        expect(options.nodes).toMatchInlineSnapshot(`
-                  Array [
-                    Object {
-                      "url": "http://node-a:9200/",
-                    },
-                  ]
-              `);
-
-        options = parseClientOptions(
-          createConfig({
             password: 'pass',
             hosts: ['http://node-A:9200'],
           }),
-          false
+          true
         );
         expect(options.nodes).toMatchInlineSnapshot(`
                   Array [
@@ -246,22 +232,6 @@ describe('parseClientOptions', () => {
                     },
                   ]
               `);
-
-        options = parseClientOptions(
-          createConfig({
-            username: 'user',
-            password: 'pass',
-            hosts: ['http://node-A:9200'],
-          }),
-          false
-        );
-        expect(options.nodes).toMatchInlineSnapshot(`
-                  Array [
-                    Object {
-                      "url": "http://user:pass@node-a:9200/",
-                    },
-                  ]
-              `);
       });
     });
     describe('when `scoped` is true', () => {
diff --git a/src/core/server/elasticsearch/client/client_config.ts b/src/core/server/elasticsearch/client/client_config.ts
index f24c0d86550b8..dab20edfc61ff 100644
--- a/src/core/server/elasticsearch/client/client_config.ts
+++ b/src/core/server/elasticsearch/client/client_config.ts
@@ -93,7 +93,7 @@ export function parseClientOptions(
     };
   }
 
-  clientOptions.nodes = config.hosts.map((host) => convertHost(host, !scoped, config));
+  clientOptions.nodes = config.hosts.map((host) => convertHost(host));
 
   if (config.ssl) {
     clientOptions.ssl = generateSslConfig(
@@ -140,18 +140,10 @@ const generateSslConfig = (
   return ssl;
 };
 
-const convertHost = (
-  host: string,
-  needAuth: boolean,
-  { username, password }: ElasticsearchClientConfig
-): NodeOptions => {
+const convertHost = (host: string): NodeOptions => {
   const url = new URL(host);
   const isHTTPS = url.protocol === 'https:';
   url.port = url.port || (isHTTPS ? '443' : '80');
-  if (needAuth && username && password) {
-    url.username = username;
-    url.password = password;
-  }
 
   return {
     url,
diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker
index f5cf6c85fcbef..274d7a4e5a488 100755
--- a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker
+++ b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker
@@ -138,6 +138,7 @@ kibana_vars=(
     tilemap.url
     timelion.enabled
     vega.enableExternalUrls
+    xpack.actions.proxyUrl
     xpack.apm.enabled
     xpack.apm.serviceMapEnabled
     xpack.apm.ui.enabled
diff --git a/src/dev/ci_setup/setup_env.sh b/src/dev/ci_setup/setup_env.sh
index 8ec80ac295c73..5dac270239c4a 100644
--- a/src/dev/ci_setup/setup_env.sh
+++ b/src/dev/ci_setup/setup_env.sh
@@ -24,6 +24,10 @@ export NODE_OPTIONS="$NODE_OPTIONS --max-old-space-size=4096"
 ###
 export FORCE_COLOR=1
 
+### APM tracking
+###
+export ELASTIC_APM_ENVIRONMENT=ci
+
 ###
 ### check that we seem to be in a kibana project
 ###
diff --git a/src/fixtures/telemetry_collectors/externally_defined_collector.ts b/src/fixtures/telemetry_collectors/externally_defined_collector.ts
index 00a8d643e27b3..decee9df28185 100644
--- a/src/fixtures/telemetry_collectors/externally_defined_collector.ts
+++ b/src/fixtures/telemetry_collectors/externally_defined_collector.ts
@@ -16,7 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { CollectorSet, CollectorOptions } from '../../plugins/usage_collection/server/collector';
+import {
+  CollectorSet,
+  UsageCollectorOptions,
+} from '../../plugins/usage_collection/server/collector';
 import { loggerMock } from '../../core/server/logging/logger.mock';
 
 const collectorSet = new CollectorSet({
@@ -28,7 +31,7 @@ interface Usage {
   locale: string;
 }
 
-function createCollector(): CollectorOptions<Usage> {
+function createCollector(): UsageCollectorOptions<Usage> {
   return {
     type: 'from_fn_collector',
     isReady: () => true,
@@ -46,7 +49,7 @@ function createCollector(): CollectorOptions<Usage> {
 }
 
 export function defineCollectorFromVariable() {
-  const fromVarCollector: CollectorOptions<Usage> = {
+  const fromVarCollector: UsageCollectorOptions<Usage> = {
     type: 'from_variable_collector',
     isReady: () => true,
     fetch(): Usage {
diff --git a/src/fixtures/telemetry_collectors/unmapped_collector.ts b/src/fixtures/telemetry_collectors/unmapped_collector.ts
index 1ea360fcd9e96..143bb168aff35 100644
--- a/src/fixtures/telemetry_collectors/unmapped_collector.ts
+++ b/src/fixtures/telemetry_collectors/unmapped_collector.ts
@@ -28,6 +28,7 @@ interface Usage {
   locale: string;
 }
 
+// @ts-expect-error Intentionally not specifying `schema`
 export const myCollector = makeUsageCollector<Usage>({
   type: 'unmapped_collector',
   isReady: () => true,
diff --git a/src/legacy/server/i18n/constants.ts b/src/legacy/server/i18n/constants.ts
index 96fa420d4c6e1..a7a410dbcb5b3 100644
--- a/src/legacy/server/i18n/constants.ts
+++ b/src/legacy/server/i18n/constants.ts
@@ -18,8 +18,3 @@
  */
 
 export const I18N_RC = '.i18nrc.json';
-
-/**
- * The type name used within the Monitoring index to publish localization stats.
- */
-export const KIBANA_LOCALIZATION_STATS_TYPE = 'localization';
diff --git a/src/legacy/server/i18n/localization/telemetry_localization_collector.ts b/src/legacy/server/i18n/localization/telemetry_localization_collector.ts
index 89566dfd4ef68..fb837f5ae28df 100644
--- a/src/legacy/server/i18n/localization/telemetry_localization_collector.ts
+++ b/src/legacy/server/i18n/localization/telemetry_localization_collector.ts
@@ -21,7 +21,6 @@ import { i18nLoader } from '@kbn/i18n';
 import { size } from 'lodash';
 import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
 import { getIntegrityHashes, Integrities } from './file_integrity';
-import { KIBANA_LOCALIZATION_STATS_TYPE } from '../constants';
 
 export interface UsageStats {
   locale: string;
@@ -63,14 +62,20 @@ export function createCollectorFetch({
   };
 }
 
+// TODO: Migrate out of the Legacy dir
 export function registerLocalizationUsageCollector(
   usageCollection: UsageCollectionSetup,
   helpers: LocalizationUsageCollectorHelpers
 ) {
-  const collector = usageCollection.makeUsageCollector({
-    type: KIBANA_LOCALIZATION_STATS_TYPE,
+  const collector = usageCollection.makeUsageCollector<UsageStats>({
+    type: 'localization',
     isReady: () => true,
     fetch: createCollectorFetch(helpers),
+    schema: {
+      locale: { type: 'keyword' },
+      integrities: { DYNAMIC_KEY: { type: 'text' } },
+      labelsCount: { type: 'long' },
+    },
   });
 
   usageCollection.registerCollector(collector);
diff --git a/src/plugins/advanced_settings/public/management_app/components/field/field.tsx b/src/plugins/advanced_settings/public/management_app/components/field/field.tsx
index 794168132abb2..e9fa2833c3db5 100644
--- a/src/plugins/advanced_settings/public/management_app/components/field/field.tsx
+++ b/src/plugins/advanced_settings/public/management_app/components/field/field.tsx
@@ -22,6 +22,7 @@ import classNames from 'classnames';
 
 import 'brace/theme/textmate';
 import 'brace/mode/markdown';
+import 'brace/mode/json';
 
 import {
   EuiBadge,
diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md
index d2439e3f1573c..81fa6d4ba20db 100644
--- a/src/plugins/data/public/public.api.md
+++ b/src/plugins/data/public/public.api.md
@@ -1598,13 +1598,13 @@ export interface OptionedValueProp {
     value: string;
 }
 
-// Warning: (ae-forgotten-export) The symbol "KbnError" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "EsError" needs to be exported by the entry point index.d.ts
 // Warning: (ae-missing-release-tag) "PainlessError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
 //
 // @public (undocumented)
-export class PainlessError extends KbnError {
-    // Warning: (ae-forgotten-export) The symbol "EsError" needs to be exported by the entry point index.d.ts
-    constructor(err: EsError, request: IKibanaSearchRequest);
+export class PainlessError extends EsError {
+    // Warning: (ae-forgotten-export) The symbol "IEsError" needs to be exported by the entry point index.d.ts
+    constructor(err: IEsError, request: IKibanaSearchRequest);
     // (undocumented)
     getErrorMessage(application: ApplicationStart): JSX.Element;
     // (undocumented)
@@ -2134,6 +2134,7 @@ export interface SearchSourceFields {
     version?: boolean;
 }
 
+// Warning: (ae-forgotten-export) The symbol "KbnError" needs to be exported by the entry point index.d.ts
 // Warning: (ae-missing-release-tag) "SearchTimeoutError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
 //
 // @public
diff --git a/src/plugins/data/public/search/errors/es_error.tsx b/src/plugins/data/public/search/errors/es_error.tsx
new file mode 100644
index 0000000000000..53d00159b836b
--- /dev/null
+++ b/src/plugins/data/public/search/errors/es_error.tsx
@@ -0,0 +1,46 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import { EuiCodeBlock, EuiSpacer } from '@elastic/eui';
+import { ApplicationStart } from 'kibana/public';
+import { KbnError } from '../../../../kibana_utils/common';
+import { IEsError } from './types';
+import { getRootCause } from './utils';
+
+export class EsError extends KbnError {
+  constructor(protected readonly err: IEsError) {
+    super('EsError');
+  }
+
+  public getErrorMessage(application: ApplicationStart) {
+    const rootCause = getRootCause(this.err)?.reason;
+
+    return (
+      <>
+        <EuiSpacer size="s" />
+        {rootCause ? (
+          <EuiCodeBlock data-test-subj="errMessage" isCopyable={true} paddingSize="s">
+            {rootCause}
+          </EuiCodeBlock>
+        ) : null}
+      </>
+    );
+  }
+}
diff --git a/src/plugins/data/public/search/errors/http_error.tsx b/src/plugins/data/public/search/errors/http_error.tsx
new file mode 100644
index 0000000000000..58ae3148804a2
--- /dev/null
+++ b/src/plugins/data/public/search/errors/http_error.tsx
@@ -0,0 +1,38 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { EuiCodeBlock, EuiSpacer } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import React from 'react';
+
+export function getHttpError(message: string) {
+  return (
+    <>
+      {i18n.translate('data.errors.fetchError', {
+        defaultMessage:
+          'Check your network and proxy configuration. If the problem persists, contact your network administrator.',
+      })}
+      <EuiSpacer size="s" />
+      <EuiSpacer size="s" />
+      <EuiCodeBlock data-test-subj="errMessage" isCopyable={true} paddingSize="s">
+        {message}
+      </EuiCodeBlock>
+    </>
+  );
+}
diff --git a/src/plugins/data/public/search/errors/index.ts b/src/plugins/data/public/search/errors/index.ts
index 6082e758a8bad..01357d25334a3 100644
--- a/src/plugins/data/public/search/errors/index.ts
+++ b/src/plugins/data/public/search/errors/index.ts
@@ -17,5 +17,9 @@
  * under the License.
  */
 
+export * from './es_error';
 export * from './painless_error';
 export * from './timeout_error';
+export * from './utils';
+export * from './types';
+export * from './http_error';
diff --git a/src/plugins/data/public/search/errors/painless_error.tsx b/src/plugins/data/public/search/errors/painless_error.tsx
index 244f205469a2f..282a602d358c7 100644
--- a/src/plugins/data/public/search/errors/painless_error.tsx
+++ b/src/plugins/data/public/search/errors/painless_error.tsx
@@ -22,22 +22,15 @@ import { i18n } from '@kbn/i18n';
 import { EuiButton, EuiSpacer, EuiText, EuiCodeBlock } from '@elastic/eui';
 import { FormattedMessage } from '@kbn/i18n/react';
 import { ApplicationStart } from 'kibana/public';
-import { KbnError } from '../../../../kibana_utils/common';
-import { EsError, isEsError } from './types';
+import { IEsError, isEsError } from './types';
+import { EsError } from './es_error';
+import { getRootCause } from './utils';
 import { IKibanaSearchRequest } from '..';
 
-export class PainlessError extends KbnError {
+export class PainlessError extends EsError {
   painlessStack?: string;
-  constructor(err: EsError, request: IKibanaSearchRequest) {
-    const rootCause = getRootCause(err as EsError);
-
-    super(
-      i18n.translate('data.painlessError.painlessScriptedFieldErrorMessage', {
-        defaultMessage: "Error executing Painless script: '{script}'.",
-        values: { script: rootCause?.script },
-      })
-    );
-    this.painlessStack = rootCause?.script_stack ? rootCause?.script_stack.join('\n') : undefined;
+  constructor(err: IEsError, request: IKibanaSearchRequest) {
+    super(err);
   }
 
   public getErrorMessage(application: ApplicationStart) {
@@ -47,14 +40,20 @@ export class PainlessError extends KbnError {
       });
     }
 
+    const rootCause = getRootCause(this.err);
+    const painlessStack = rootCause?.script_stack ? rootCause?.script_stack.join('\n') : undefined;
+
     return (
       <>
-        {this.message}
+        {i18n.translate('data.painlessError.painlessScriptedFieldErrorMessage', {
+          defaultMessage: "Error executing Painless script: '{script}'.",
+          values: { script: rootCause?.script },
+        })}
         <EuiSpacer size="s" />
         <EuiSpacer size="s" />
-        {this.painlessStack ? (
+        {painlessStack ? (
           <EuiCodeBlock data-test-subj="painlessStackTrace" isCopyable={true} paddingSize="s">
-            {this.painlessStack}
+            {painlessStack}
           </EuiCodeBlock>
         ) : null}
         <EuiText textAlign="right">
@@ -67,21 +66,10 @@ export class PainlessError extends KbnError {
   }
 }
 
-function getFailedShards(err: EsError) {
-  const failedShards =
-    err.body?.attributes?.error?.failed_shards ||
-    err.body?.attributes?.error?.caused_by?.failed_shards;
-  return failedShards ? failedShards[0] : undefined;
-}
-
-function getRootCause(err: EsError) {
-  return getFailedShards(err)?.reason;
-}
-
-export function isPainlessError(err: Error | EsError) {
+export function isPainlessError(err: Error | IEsError) {
   if (!isEsError(err)) return false;
 
-  const rootCause = getRootCause(err as EsError);
+  const rootCause = getRootCause(err as IEsError);
   if (!rootCause) return false;
 
   const { lang } = rootCause;
diff --git a/src/plugins/data/public/search/errors/types.ts b/src/plugins/data/public/search/errors/types.ts
index 4182209eb68a5..011af015318a7 100644
--- a/src/plugins/data/public/search/errors/types.ts
+++ b/src/plugins/data/public/search/errors/types.ts
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-interface FailedShard {
+export interface FailedShard {
   shard: number;
   index: string;
   node: string;
@@ -39,7 +39,7 @@ interface FailedShard {
   };
 }
 
-export interface EsError {
+export interface IEsError {
   body: {
     statusCode: number;
     error: string;
@@ -68,6 +68,6 @@ export interface EsError {
   };
 }
 
-export function isEsError(e: any): e is EsError {
+export function isEsError(e: any): e is IEsError {
   return !!e.body?.attributes;
 }
diff --git a/src/plugins/data/public/search/errors/utils.ts b/src/plugins/data/public/search/errors/utils.ts
new file mode 100644
index 0000000000000..d07d9b05e91e9
--- /dev/null
+++ b/src/plugins/data/public/search/errors/utils.ts
@@ -0,0 +1,31 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { IEsError } from './types';
+
+export function getFailedShards(err: IEsError) {
+  const failedShards =
+    err.body?.attributes?.error?.failed_shards ||
+    err.body?.attributes?.error?.caused_by?.failed_shards;
+  return failedShards ? failedShards[0] : undefined;
+}
+
+export function getRootCause(err: IEsError) {
+  return getFailedShards(err)?.reason;
+}
diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts
index e3c6dd3e287d4..1afcf4615ab5a 100644
--- a/src/plugins/data/public/search/search_interceptor.ts
+++ b/src/plugins/data/public/search/search_interceptor.ts
@@ -21,6 +21,7 @@ import { get, memoize, trimEnd } from 'lodash';
 import { BehaviorSubject, throwError, timer, defer, from, Observable, NEVER } from 'rxjs';
 import { catchError, finalize } from 'rxjs/operators';
 import { CoreStart, CoreSetup, ToastsSetup } from 'kibana/public';
+import { i18n } from '@kbn/i18n';
 import {
   getCombinedSignal,
   AbortError,
@@ -31,7 +32,15 @@ import {
   ISessionService,
 } from '../../common';
 import { SearchUsageCollector } from './collectors';
-import { SearchTimeoutError, PainlessError, isPainlessError, TimeoutErrorMode } from './errors';
+import {
+  SearchTimeoutError,
+  PainlessError,
+  isPainlessError,
+  TimeoutErrorMode,
+  isEsError,
+  EsError,
+  getHttpError,
+} from './errors';
 import { toMountPoint } from '../../../kibana_react/public';
 
 export interface SearchInterceptorDeps {
@@ -101,8 +110,12 @@ export class SearchInterceptor {
     } else if (options?.abortSignal?.aborted) {
       // In the case an application initiated abort, throw the existing AbortError.
       return e;
-    } else if (isPainlessError(e)) {
-      return new PainlessError(e, request);
+    } else if (isEsError(e)) {
+      if (isPainlessError(e)) {
+        return new PainlessError(e, request);
+      } else {
+        return new EsError(e);
+      }
     } else {
       return e;
     }
@@ -236,24 +249,28 @@ export class SearchInterceptor {
    *
    */
   public showError(e: Error) {
-    if (e instanceof AbortError) return;
-
-    if (e instanceof SearchTimeoutError) {
+    if (e instanceof AbortError || e instanceof SearchTimeoutError) {
       // The SearchTimeoutError is shown by the interceptor in getSearchError (regardless of how the app chooses to handle errors)
       return;
-    }
-
-    if (e instanceof PainlessError) {
+    } else if (e instanceof EsError) {
       this.deps.toasts.addDanger({
-        title: 'Search Error',
+        title: i18n.translate('data.search.esErrorTitle', {
+          defaultMessage: 'Cannot retrieve search results',
+        }),
         text: toMountPoint(e.getErrorMessage(this.application)),
       });
-      return;
+    } else if (e.constructor.name === 'HttpFetchError') {
+      this.deps.toasts.addDanger({
+        title: i18n.translate('data.search.httpErrorTitle', {
+          defaultMessage: 'Cannot retrieve your data',
+        }),
+        text: toMountPoint(getHttpError(e.message)),
+      });
+    } else {
+      this.deps.toasts.addError(e, {
+        title: 'Search Error',
+      });
     }
-
-    this.deps.toasts.addError(e, {
-      title: 'Search Error',
-    });
   }
 }
 
diff --git a/src/plugins/data/public/ui/query_string_input/query_string_input.tsx b/src/plugins/data/public/ui/query_string_input/query_string_input.tsx
index c17872028ea8d..bc9e2ed6a83ce 100644
--- a/src/plugins/data/public/ui/query_string_input/query_string_input.tsx
+++ b/src/plugins/data/public/ui/query_string_input/query_string_input.tsx
@@ -111,6 +111,7 @@ export default class QueryStringInputUI extends Component<Props, State> {
 
   private persistedLog: PersistedLog | undefined;
   private abortController?: AbortController;
+  private fetchIndexPatternsAbortController?: AbortController;
   private services = this.props.kibana.services;
   private componentIsUnmounting = false;
   private queryBarInputDivRefInstance: RefObject<HTMLDivElement> = createRef();
@@ -119,7 +120,7 @@ export default class QueryStringInputUI extends Component<Props, State> {
     return toUser(this.props.query.query);
   };
 
-  private fetchIndexPatterns = async () => {
+  private fetchIndexPatterns = debounce(async () => {
     const stringPatterns = this.props.indexPatterns.filter(
       (indexPattern) => typeof indexPattern === 'string'
     ) as string[];
@@ -127,16 +128,26 @@ export default class QueryStringInputUI extends Component<Props, State> {
       (indexPattern) => typeof indexPattern !== 'string'
     ) as IIndexPattern[];
 
+    // abort the previous fetch to avoid overriding with outdated data
+    // issue https://github.com/elastic/kibana/issues/80831
+    if (this.fetchIndexPatternsAbortController) this.fetchIndexPatternsAbortController.abort();
+    this.fetchIndexPatternsAbortController = new AbortController();
+    const currentAbortController = this.fetchIndexPatternsAbortController;
+
     const objectPatternsFromStrings = (await fetchIndexPatterns(
       this.services.savedObjects!.client,
       stringPatterns,
       this.services.uiSettings!
     )) as IIndexPattern[];
 
-    this.setState({
-      indexPatterns: [...objectPatterns, ...objectPatternsFromStrings],
-    });
-  };
+    if (!currentAbortController.signal.aborted) {
+      this.setState({
+        indexPatterns: [...objectPatterns, ...objectPatternsFromStrings],
+      });
+
+      this.updateSuggestions();
+    }
+  }, 200);
 
   private getSuggestions = async () => {
     if (!this.inputRef) {
@@ -506,7 +517,7 @@ export default class QueryStringInputUI extends Component<Props, State> {
     }
 
     this.initPersistedLog();
-    this.fetchIndexPatterns().then(this.updateSuggestions);
+    this.fetchIndexPatterns();
     this.handleListUpdate();
 
     window.addEventListener('resize', this.handleAutoHeight);
@@ -525,7 +536,7 @@ export default class QueryStringInputUI extends Component<Props, State> {
     this.initPersistedLog();
 
     if (!isEqual(prevProps.indexPatterns, this.props.indexPatterns)) {
-      this.fetchIndexPatterns().then(this.updateSuggestions);
+      this.fetchIndexPatterns();
     } else if (!isEqual(prevProps.query, this.props.query)) {
       this.updateSuggestions();
     }
diff --git a/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts b/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts
index 57c636a9e3c69..e75b8761984ec 100644
--- a/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import { LegacyAPICaller } from 'kibana/server';
+import { ElasticsearchClient } from 'kibana/server';
 
 import { getFieldCapabilities, resolveTimePattern, createNoMatchingIndicesError } from './lib';
 
@@ -37,10 +37,12 @@ interface FieldSubType {
 }
 
 export class IndexPatternsFetcher {
-  private _callDataCluster: LegacyAPICaller;
+  private elasticsearchClient: ElasticsearchClient;
+  private allowNoIndices: boolean;
 
-  constructor(callDataCluster: LegacyAPICaller) {
-    this._callDataCluster = callDataCluster;
+  constructor(elasticsearchClient: ElasticsearchClient, allowNoIndices: boolean = false) {
+    this.elasticsearchClient = elasticsearchClient;
+    this.allowNoIndices = allowNoIndices;
   }
 
   /**
@@ -55,10 +57,12 @@ export class IndexPatternsFetcher {
   async getFieldsForWildcard(options: {
     pattern: string | string[];
     metaFields?: string[];
-    fieldCapsOptions?: { allowNoIndices: boolean };
+    fieldCapsOptions?: { allow_no_indices: boolean };
   }): Promise<FieldDescriptor[]> {
     const { pattern, metaFields, fieldCapsOptions } = options;
-    return await getFieldCapabilities(this._callDataCluster, pattern, metaFields, fieldCapsOptions);
+    return await getFieldCapabilities(this.elasticsearchClient, pattern, metaFields, {
+      allow_no_indices: fieldCapsOptions ? fieldCapsOptions.allow_no_indices : this.allowNoIndices,
+    });
   }
 
   /**
@@ -78,11 +82,11 @@ export class IndexPatternsFetcher {
     interval: string;
   }) {
     const { pattern, lookBack, metaFields } = options;
-    const { matches } = await resolveTimePattern(this._callDataCluster, pattern);
+    const { matches } = await resolveTimePattern(this.elasticsearchClient, pattern);
     const indices = matches.slice(0, lookBack);
     if (indices.length === 0) {
       throw createNoMatchingIndicesError(pattern);
     }
-    return await getFieldCapabilities(this._callDataCluster, indices, metaFields);
+    return await getFieldCapabilities(this.elasticsearchClient, indices, metaFields);
   }
 }
diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/es_api.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.test.js
index 8078ea32187b3..fad20a8f0be06 100644
--- a/src/plugins/data/server/index_patterns/fetcher/lib/es_api.test.js
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.test.js
@@ -32,36 +32,60 @@ describe('server/index_patterns/service/lib/es_api', () => {
     afterEach(() => sandbox.restore());
 
     it('calls indices.getAlias() via callCluster', async () => {
-      const callCluster = sinon.stub();
+      const getAlias = sinon.stub();
+      const callCluster = {
+        indices: {
+          getAlias,
+        },
+        fieldCaps: sinon.stub(),
+      };
+
       await callIndexAliasApi(callCluster);
-      sinon.assert.calledOnce(callCluster);
-      sinon.assert.calledWith(callCluster, 'indices.getAlias');
+      sinon.assert.calledOnce(getAlias);
     });
 
     it('passes indices directly to es api', async () => {
       const football = {};
-      const callCluster = sinon.stub();
+      const getAlias = sinon.stub();
+      const callCluster = {
+        indices: {
+          getAlias,
+        },
+        fieldCaps: sinon.stub(),
+      };
       await callIndexAliasApi(callCluster, football);
-      sinon.assert.calledOnce(callCluster);
-      expect(callCluster.args[0][1].index).toBe(football);
+      sinon.assert.calledOnce(getAlias);
+      expect(getAlias.args[0][0].index).toBe(football);
     });
 
     it('returns the es response directly', async () => {
       const football = {};
-      const callCluster = sinon.stub().returns(football);
+      const getAlias = sinon.stub().returns(football);
+      const callCluster = {
+        indices: {
+          getAlias,
+        },
+        fieldCaps: sinon.stub(),
+      };
       const resp = await callIndexAliasApi(callCluster);
-      sinon.assert.calledOnce(callCluster);
+      sinon.assert.calledOnce(getAlias);
       expect(resp).toBe(football);
     });
 
     it('sets ignoreUnavailable and allowNoIndices params', async () => {
-      const callCluster = sinon.stub();
+      const getAlias = sinon.stub();
+      const callCluster = {
+        indices: {
+          getAlias,
+        },
+        fieldCaps: sinon.stub(),
+      };
       await callIndexAliasApi(callCluster);
-      sinon.assert.calledOnce(callCluster);
+      sinon.assert.calledOnce(getAlias);
 
-      const passedOpts = callCluster.args[0][1];
-      expect(passedOpts).toHaveProperty('ignoreUnavailable', true);
-      expect(passedOpts).toHaveProperty('allowNoIndices', false);
+      const passedOpts = getAlias.args[0][0];
+      expect(passedOpts).toHaveProperty('ignore_unavailable', true);
+      expect(passedOpts).toHaveProperty('allow_no_indices', false);
     });
 
     it('handles errors with convertEsError()', async () => {
@@ -70,9 +94,15 @@ describe('server/index_patterns/service/lib/es_api', () => {
       const convertedError = new Error('convertedError');
 
       sandbox.stub(convertEsErrorNS, 'convertEsError').throws(convertedError);
-      const callCluster = sinon.spy(async () => {
+      const getAlias = sinon.stub(async () => {
         throw esError;
       });
+      const callCluster = {
+        indices: {
+          getAlias,
+        },
+        fieldCaps: sinon.stub(),
+      };
       try {
         await callIndexAliasApi(callCluster, indices);
         throw new Error('expected callIndexAliasApi() to throw');
@@ -91,37 +121,60 @@ describe('server/index_patterns/service/lib/es_api', () => {
     afterEach(() => sandbox.restore());
 
     it('calls fieldCaps() via callCluster', async () => {
-      const callCluster = sinon.stub();
+      const fieldCaps = sinon.stub();
+      const callCluster = {
+        indices: {
+          getAlias: sinon.stub(),
+        },
+        fieldCaps,
+      };
       await callFieldCapsApi(callCluster);
-      sinon.assert.calledOnce(callCluster);
-      sinon.assert.calledWith(callCluster, 'fieldCaps');
+      sinon.assert.calledOnce(fieldCaps);
     });
 
     it('passes indices directly to es api', async () => {
       const football = {};
-      const callCluster = sinon.stub();
+      const fieldCaps = sinon.stub();
+      const callCluster = {
+        indices: {
+          getAlias: sinon.stub(),
+        },
+        fieldCaps,
+      };
       await callFieldCapsApi(callCluster, football);
-      sinon.assert.calledOnce(callCluster);
-      expect(callCluster.args[0][1].index).toBe(football);
+      sinon.assert.calledOnce(fieldCaps);
+      expect(fieldCaps.args[0][0].index).toBe(football);
     });
 
     it('returns the es response directly', async () => {
       const football = {};
-      const callCluster = sinon.stub().returns(football);
+      const fieldCaps = sinon.stub().returns(football);
+      const callCluster = {
+        indices: {
+          getAlias: sinon.stub(),
+        },
+        fieldCaps,
+      };
       const resp = await callFieldCapsApi(callCluster);
-      sinon.assert.calledOnce(callCluster);
+      sinon.assert.calledOnce(fieldCaps);
       expect(resp).toBe(football);
     });
 
     it('sets ignoreUnavailable, allowNoIndices, and fields params', async () => {
-      const callCluster = sinon.stub();
+      const fieldCaps = sinon.stub();
+      const callCluster = {
+        indices: {
+          getAlias: sinon.stub(),
+        },
+        fieldCaps,
+      };
       await callFieldCapsApi(callCluster);
-      sinon.assert.calledOnce(callCluster);
+      sinon.assert.calledOnce(fieldCaps);
 
-      const passedOpts = callCluster.args[0][1];
+      const passedOpts = fieldCaps.args[0][0];
       expect(passedOpts).toHaveProperty('fields', '*');
-      expect(passedOpts).toHaveProperty('ignoreUnavailable', true);
-      expect(passedOpts).toHaveProperty('allowNoIndices', false);
+      expect(passedOpts).toHaveProperty('ignore_unavailable', true);
+      expect(passedOpts).toHaveProperty('allow_no_indices', false);
     });
 
     it('handles errors with convertEsError()', async () => {
@@ -130,9 +183,15 @@ describe('server/index_patterns/service/lib/es_api', () => {
       const convertedError = new Error('convertedError');
 
       sandbox.stub(convertEsErrorNS, 'convertEsError').throws(convertedError);
-      const callCluster = sinon.spy(async () => {
+      const fieldCaps = sinon.spy(async () => {
         throw esError;
       });
+      const callCluster = {
+        indices: {
+          getAlias: sinon.stub(),
+        },
+        fieldCaps,
+      };
       try {
         await callFieldCapsApi(callCluster, indices);
         throw new Error('expected callFieldCapsApi() to throw');
diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts
index 27ce14f9a3597..7969324943a9f 100644
--- a/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import { LegacyAPICaller } from 'kibana/server';
+import { ElasticsearchClient } from 'kibana/server';
 import { convertEsError } from './errors';
 import { FieldCapsResponse } from './field_capabilities';
 
@@ -46,15 +46,15 @@ export interface IndexAliasResponse {
  *  @return {Promise<IndexAliasResponse>}
  */
 export async function callIndexAliasApi(
-  callCluster: LegacyAPICaller,
+  callCluster: ElasticsearchClient,
   indices: string[] | string
-): Promise<IndicesAliasResponse> {
+) {
   try {
-    return (await callCluster('indices.getAlias', {
+    return await callCluster.indices.getAlias({
       index: indices,
-      ignoreUnavailable: true,
-      allowNoIndices: false,
-    })) as Promise<IndicesAliasResponse>;
+      ignore_unavailable: true,
+      allow_no_indices: false,
+    });
   } catch (error) {
     throw convertEsError(indices, error);
   }
@@ -73,17 +73,17 @@ export async function callIndexAliasApi(
  *  @return {Promise<FieldCapsResponse>}
  */
 export async function callFieldCapsApi(
-  callCluster: LegacyAPICaller,
+  callCluster: ElasticsearchClient,
   indices: string[] | string,
-  fieldCapsOptions: { allowNoIndices: boolean } = { allowNoIndices: false }
+  fieldCapsOptions: { allow_no_indices: boolean } = { allow_no_indices: false }
 ) {
   try {
-    return (await callCluster('fieldCaps', {
+    return await callCluster.fieldCaps<FieldCapsResponse>({
       index: indices,
       fields: '*',
-      ignoreUnavailable: true,
+      ignore_unavailable: true,
       ...fieldCapsOptions,
-    })) as FieldCapsResponse;
+    });
   } catch (error) {
     throw convertEsError(indices, error);
   }
diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.test.js
index 0e5757b7b782b..2d860dc8b1843 100644
--- a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.test.js
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.test.js
@@ -48,9 +48,11 @@ describe('index_patterns/field_capabilities/field_capabilities', () => {
   };
 
   const stubDeps = (options = {}) => {
-    const { esResponse = {}, fieldsFromFieldCaps = [], mergeOverrides = identity } = options;
+    const { esResponse = [], fieldsFromFieldCaps = [], mergeOverrides = identity } = options;
 
-    sandbox.stub(callFieldCapsApiNS, 'callFieldCapsApi').callsFake(async () => esResponse);
+    sandbox
+      .stub(callFieldCapsApiNS, 'callFieldCapsApi')
+      .callsFake(async () => ({ body: esResponse }));
     sandbox.stub(readFieldCapsResponseNS, 'readFieldCapsResponse').returns(fieldsFromFieldCaps);
     sandbox.stub(mergeOverridesNS, 'mergeOverrides').callsFake(mergeOverrides);
   };
diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts
index 62e77e0adad66..b9e3e8aae0899 100644
--- a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts
@@ -19,9 +19,9 @@
 
 import { defaults, keyBy, sortBy } from 'lodash';
 
-import { LegacyAPICaller } from 'kibana/server';
+import { ElasticsearchClient } from 'kibana/server';
 import { callFieldCapsApi } from '../es_api';
-import { FieldCapsResponse, readFieldCapsResponse } from './field_caps_response';
+import { readFieldCapsResponse } from './field_caps_response';
 import { mergeOverrides } from './overrides';
 import { FieldDescriptor } from '../../index_patterns_fetcher';
 
@@ -36,17 +36,13 @@ import { FieldDescriptor } from '../../index_patterns_fetcher';
  *  @return {Promise<Array<FieldDescriptor>>}
  */
 export async function getFieldCapabilities(
-  callCluster: LegacyAPICaller,
+  callCluster: ElasticsearchClient,
   indices: string | string[] = [],
   metaFields: string[] = [],
-  fieldCapsOptions?: { allowNoIndices: boolean }
+  fieldCapsOptions?: { allow_no_indices: boolean }
 ) {
-  const esFieldCaps: FieldCapsResponse = await callFieldCapsApi(
-    callCluster,
-    indices,
-    fieldCapsOptions
-  );
-  const fieldsFromFieldCapsByName = keyBy(readFieldCapsResponse(esFieldCaps), 'name');
+  const esFieldCaps = await callFieldCapsApi(callCluster, indices, fieldCapsOptions);
+  const fieldsFromFieldCapsByName = keyBy(readFieldCapsResponse(esFieldCaps.body), 'name');
 
   const allFieldsUnsorted = Object.keys(fieldsFromFieldCapsByName)
     .filter((name) => !name.startsWith('_'))
diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.test.js
index 660e9ec30db6a..87f222aaad89d 100644
--- a/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.test.js
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.test.js
@@ -32,6 +32,11 @@ const TIME_PATTERN = '[logs-]dddd-YYYY.w';
 
 describe('server/index_patterns/service/lib/resolve_time_pattern', () => {
   let sandbox;
+  const esClientMock = {
+    indices: {
+      getAlias: () => ({}),
+    },
+  };
   beforeEach(() => (sandbox = sinon.createSandbox()));
   afterEach(() => sandbox.restore());
 
@@ -39,7 +44,7 @@ describe('server/index_patterns/service/lib/resolve_time_pattern', () => {
     describe('pre request', () => {
       it('uses callIndexAliasApi() fn', async () => {
         sandbox.stub(callIndexAliasApiNS, 'callIndexAliasApi').returns({});
-        await resolveTimePattern(noop, TIME_PATTERN);
+        await resolveTimePattern(esClientMock, TIME_PATTERN);
         sinon.assert.calledOnce(callIndexAliasApi);
       });
 
@@ -49,7 +54,7 @@ describe('server/index_patterns/service/lib/resolve_time_pattern', () => {
 
         sandbox.stub(timePatternToWildcardNS, 'timePatternToWildcard').returns(wildcard);
 
-        await resolveTimePattern(noop, timePattern);
+        await resolveTimePattern(esClientMock, timePattern);
         sinon.assert.calledOnce(timePatternToWildcard);
         expect(timePatternToWildcard.firstCall.args).toEqual([timePattern]);
       });
@@ -61,7 +66,7 @@ describe('server/index_patterns/service/lib/resolve_time_pattern', () => {
         sandbox.stub(callIndexAliasApiNS, 'callIndexAliasApi').returns({});
         sandbox.stub(timePatternToWildcardNS, 'timePatternToWildcard').returns(wildcard);
 
-        await resolveTimePattern(noop, timePattern);
+        await resolveTimePattern(esClientMock, timePattern);
         sinon.assert.calledOnce(callIndexAliasApi);
         expect(callIndexAliasApi.firstCall.args[1]).toBe(wildcard);
       });
@@ -70,13 +75,15 @@ describe('server/index_patterns/service/lib/resolve_time_pattern', () => {
     describe('read response', () => {
       it('returns all aliases names in result.all, ordered by time desc', async () => {
         sandbox.stub(callIndexAliasApiNS, 'callIndexAliasApi').returns({
-          'logs-2016.2': {},
-          'logs-Saturday-2017.1': {},
-          'logs-2016.1': {},
-          'logs-Sunday-2017.1': {},
-          'logs-2015': {},
-          'logs-2016.3': {},
-          'logs-Friday-2017.1': {},
+          body: {
+            'logs-2016.2': {},
+            'logs-Saturday-2017.1': {},
+            'logs-2016.1': {},
+            'logs-Sunday-2017.1': {},
+            'logs-2015': {},
+            'logs-2016.3': {},
+            'logs-Friday-2017.1': {},
+          },
         });
 
         const resp = await resolveTimePattern(noop, TIME_PATTERN);
@@ -94,13 +101,15 @@ describe('server/index_patterns/service/lib/resolve_time_pattern', () => {
 
       it('returns all indices matching the time pattern in matches, ordered by time desc', async () => {
         sandbox.stub(callIndexAliasApiNS, 'callIndexAliasApi').returns({
-          'logs-2016.2': {},
-          'logs-Saturday-2017.1': {},
-          'logs-2016.1': {},
-          'logs-Sunday-2017.1': {},
-          'logs-2015': {},
-          'logs-2016.3': {},
-          'logs-Friday-2017.1': {},
+          body: {
+            'logs-2016.2': {},
+            'logs-Saturday-2017.1': {},
+            'logs-2016.1': {},
+            'logs-Sunday-2017.1': {},
+            'logs-2015': {},
+            'logs-2016.3': {},
+            'logs-Friday-2017.1': {},
+          },
         });
 
         const resp = await resolveTimePattern(noop, TIME_PATTERN);
diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts b/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts
index 2e408d7569be5..95ec06dd9c6e6 100644
--- a/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts
@@ -20,7 +20,7 @@
 import { chain } from 'lodash';
 import moment from 'moment';
 
-import { LegacyAPICaller } from 'kibana/server';
+import { ElasticsearchClient } from 'kibana/server';
 
 import { timePatternToWildcard } from './time_pattern_to_wildcard';
 import { callIndexAliasApi, IndicesAliasResponse } from './es_api';
@@ -36,10 +36,10 @@ import { callIndexAliasApi, IndicesAliasResponse } from './es_api';
  *                            and the indices that actually match the time
  *                            pattern (matches);
  */
-export async function resolveTimePattern(callCluster: LegacyAPICaller, timePattern: string) {
+export async function resolveTimePattern(callCluster: ElasticsearchClient, timePattern: string) {
   const aliases = await callIndexAliasApi(callCluster, timePatternToWildcard(timePattern));
 
-  const allIndexDetails = chain<IndicesAliasResponse>(aliases)
+  const allIndexDetails = chain<IndicesAliasResponse>(aliases.body)
     .reduce(
       (acc: string[], index: any, indexName: string) =>
         acc.concat(indexName, Object.keys(index.aliases || {})),
diff --git a/src/plugins/data/server/index_patterns/routes.ts b/src/plugins/data/server/index_patterns/routes.ts
index 428e7fef6deea..041eb235d01e0 100644
--- a/src/plugins/data/server/index_patterns/routes.ts
+++ b/src/plugins/data/server/index_patterns/routes.ts
@@ -46,8 +46,8 @@ export function registerRoutes(http: HttpServiceSetup) {
       },
     },
     async (context, request, response) => {
-      const { callAsCurrentUser } = context.core.elasticsearch.legacy.client;
-      const indexPatterns = new IndexPatternsFetcher(callAsCurrentUser);
+      const { asCurrentUser } = context.core.elasticsearch.client;
+      const indexPatterns = new IndexPatternsFetcher(asCurrentUser);
       const { pattern, meta_fields: metaFields } = request.query;
 
       let parsedFields: string[] = [];
@@ -105,8 +105,8 @@ export function registerRoutes(http: HttpServiceSetup) {
       },
     },
     async (context: RequestHandlerContext, request: any, response: any) => {
-      const { callAsCurrentUser } = context.core.elasticsearch.legacy.client;
-      const indexPatterns = new IndexPatternsFetcher(callAsCurrentUser);
+      const { asCurrentUser } = context.core.elasticsearch.client;
+      const indexPatterns = new IndexPatternsFetcher(asCurrentUser);
       const { pattern, interval, look_back: lookBack, meta_fields: metaFields } = request.query;
 
       let parsedFields: string[] = [];
diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md
index 3143d5baa5b77..97cbb40c13db0 100644
--- a/src/plugins/data/server/server.api.md
+++ b/src/plugins/data/server/server.api.md
@@ -26,6 +26,7 @@ import { ISearchSource } from 'src/plugins/data/public';
 import { KibanaRequest } from 'src/core/server';
 import { LegacyAPICaller } from 'kibana/server';
 import { Logger } from 'kibana/server';
+import { Logger as Logger_2 } from 'src/core/server';
 import { LoggerFactory } from '@kbn/logging';
 import { Moment } from 'moment';
 import moment from 'moment';
@@ -658,7 +659,7 @@ export const indexPatterns: {
 //
 // @public (undocumented)
 export class IndexPatternsFetcher {
-    constructor(callDataCluster: LegacyAPICaller);
+    constructor(elasticsearchClient: ElasticsearchClient, allowNoIndices?: boolean);
     getFieldsForTimePattern(options: {
         pattern: string;
         metaFields: string[];
@@ -669,7 +670,7 @@ export class IndexPatternsFetcher {
         pattern: string | string[];
         metaFields?: string[];
         fieldCapsOptions?: {
-            allowNoIndices: boolean;
+            allow_no_indices: boolean;
         };
     }): Promise<FieldDescriptor[]>;
 }
diff --git a/src/plugins/discover/public/application/angular/context_app.html b/src/plugins/discover/public/application/angular/context_app.html
index d609a497c4ba1..ef7bc09206176 100644
--- a/src/plugins/discover/public/application/angular/context_app.html
+++ b/src/plugins/discover/public/application/angular/context_app.html
@@ -10,7 +10,6 @@
 >
 </kbn-top-nav>
 
-
 <!-- Error feedback -->
 <context-error-message
   status="contextApp.state.loadingStatus.anchor.status"
@@ -21,20 +20,6 @@
   class="kuiViewContent kuiViewContentItem"
   ng-if="contextApp.state.loadingStatus.anchor.status !== contextApp.constants.LOADING_STATUS.FAILED"
 >
-  <!-- Controls -->
-  <context-action-bar
-        default-step-size="contextApp.state.queryParameters.defaultStepSize"
-        doc-count="contextApp.state.queryParameters.predecessorCount"
-        doc-count-available="contextApp.state.rows.predecessors.length"
-        is-disabled="contextApp.state.loadingStatus.anchor.status !== contextApp.constants.LOADING_STATUS.LOADED"
-        is-loading="![
-        contextApp.constants.LOADING_STATUS.LOADED,
-        contextApp.constants.LOADING_STATUS.FAILED,
-        ].includes(contextApp.state.loadingStatus.predecessors.status)"
-        on-change-count="contextApp.actions.fetchGivenPredecessorRows"
-        type="'predecessors'"
-  ></context-action-bar>
-
   <!-- Table -->
   <context-app-legacy
     filter="contextApp.actions.addFilter"
@@ -42,22 +27,16 @@
     index-pattern="contextApp.indexPattern"
     sorting="contextApp.state.queryParameters.sort"
     columns="contextApp.state.queryParameters.columns"
-    infinite-scroll="true"
     minimum-visible-rows="contextApp.state.rows.all.length"
     status="contextApp.state.loadingStatus.anchor.status"
-  ></context-app-legacy>
-
-  <!-- Controls -->
-  <context-action-bar
     default-step-size="contextApp.state.queryParameters.defaultStepSize"
-    doc-count="contextApp.state.queryParameters.successorCount"
-    doc-count-available="contextApp.state.rows.successors.length"
-    is-disabled="contextApp.state.loadingStatus.anchor.status !== contextApp.constants.LOADING_STATUS.LOADED"
-    is-loading="![
-    contextApp.constants.LOADING_STATUS.LOADED,
-    contextApp.constants.LOADING_STATUS.FAILED,
-    ].includes(contextApp.state.loadingStatus.successors.status)"
-    on-change-count="contextApp.actions.fetchGivenSuccessorRows"
-    type="'successors'"
-  ></context-action-bar>
+    predecessor-count="contextApp.state.queryParameters.predecessorCount"
+    predecessor-available="contextApp.state.rows.predecessors.length"
+    predecessor-status="contextApp.state.loadingStatus.predecessors.status"
+    on-change-predecessor-count="contextApp.actions.fetchGivenPredecessorRows"
+    successor-count="contextApp.state.queryParameters.successorCount"
+    successor-available="contextApp.state.rows.successors.length"
+    successor-status="contextApp.state.loadingStatus.successors.status"
+    on-change-successor-count="contextApp.actions.fetchGivenSuccessorRows"
+  ></context-app-legacy>
 </main>
diff --git a/src/plugins/discover/public/application/components/context_app/__snapshots__/context_app_legacy.test.tsx.snap b/src/plugins/discover/public/application/components/context_app/__snapshots__/context_app_legacy.test.tsx.snap
deleted file mode 100644
index 58305ee23cb21..0000000000000
--- a/src/plugins/discover/public/application/components/context_app/__snapshots__/context_app_legacy.test.tsx.snap
+++ /dev/null
@@ -1,741 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`ContextAppLegacy test renders correctly 1`] = `
-<ContextAppLegacy
-  columns={
-    Array [
-      "_source",
-    ]
-  }
-  filter={[Function]}
-  hits={
-    Array [
-      Object {
-        "_id": "123",
-        "_index": "test_index",
-        "_score": null,
-        "_source": Object {
-          "category": Array [
-            "Men's Clothing",
-          ],
-          "currency": "EUR",
-          "customer_first_name": "Walker",
-          "customer_full_name": "Walker Texas Ranger",
-          "customer_gender": "MALE",
-          "customer_last_name": "Ranger",
-        },
-        "_version": 1,
-        "fields": Array [
-          Object {
-            "order_date": Array [
-              "2020-10-19T13:35:02.000Z",
-            ],
-          },
-        ],
-        "sort": Array [
-          1603114502000,
-          2092,
-        ],
-      },
-    ]
-  }
-  indexPattern={
-    Object {
-      "id": "test_index_pattern",
-    }
-  }
-  infiniteScroll={true}
-  intl={
-    Object {
-      "defaultFormats": Object {},
-      "defaultLocale": "en",
-      "formatDate": [Function],
-      "formatHTMLMessage": [Function],
-      "formatMessage": [Function],
-      "formatNumber": [Function],
-      "formatPlural": [Function],
-      "formatRelative": [Function],
-      "formatTime": [Function],
-      "formats": Object {
-        "date": Object {
-          "full": Object {
-            "day": "numeric",
-            "month": "long",
-            "weekday": "long",
-            "year": "numeric",
-          },
-          "long": Object {
-            "day": "numeric",
-            "month": "long",
-            "year": "numeric",
-          },
-          "medium": Object {
-            "day": "numeric",
-            "month": "short",
-            "year": "numeric",
-          },
-          "short": Object {
-            "day": "numeric",
-            "month": "numeric",
-            "year": "2-digit",
-          },
-        },
-        "number": Object {
-          "currency": Object {
-            "style": "currency",
-          },
-          "percent": Object {
-            "style": "percent",
-          },
-        },
-        "relative": Object {
-          "days": Object {
-            "units": "day",
-          },
-          "hours": Object {
-            "units": "hour",
-          },
-          "minutes": Object {
-            "units": "minute",
-          },
-          "months": Object {
-            "units": "month",
-          },
-          "seconds": Object {
-            "units": "second",
-          },
-          "years": Object {
-            "units": "year",
-          },
-        },
-        "time": Object {
-          "full": Object {
-            "hour": "numeric",
-            "minute": "numeric",
-            "second": "numeric",
-            "timeZoneName": "short",
-          },
-          "long": Object {
-            "hour": "numeric",
-            "minute": "numeric",
-            "second": "numeric",
-            "timeZoneName": "short",
-          },
-          "medium": Object {
-            "hour": "numeric",
-            "minute": "numeric",
-            "second": "numeric",
-          },
-          "short": Object {
-            "hour": "numeric",
-            "minute": "numeric",
-          },
-        },
-      },
-      "formatters": Object {
-        "getDateTimeFormat": [Function],
-        "getMessageFormat": [Function],
-        "getNumberFormat": [Function],
-        "getPluralFormat": [Function],
-        "getRelativeFormat": [Function],
-      },
-      "locale": "en",
-      "messages": Object {},
-      "now": [Function],
-      "onError": [Function],
-      "textComponent": Symbol(react.fragment),
-      "timeZone": null,
-    }
-  }
-  minimumVisibleRows={5}
-  sorting={
-    Array [
-      "order_date",
-      "desc",
-    ]
-  }
-  status="loaded"
->
-  <I18nProvider>
-    <IntlProvider
-      defaultLocale="en"
-      formats={
-        Object {
-          "date": Object {
-            "full": Object {
-              "day": "numeric",
-              "month": "long",
-              "weekday": "long",
-              "year": "numeric",
-            },
-            "long": Object {
-              "day": "numeric",
-              "month": "long",
-              "year": "numeric",
-            },
-            "medium": Object {
-              "day": "numeric",
-              "month": "short",
-              "year": "numeric",
-            },
-            "short": Object {
-              "day": "numeric",
-              "month": "numeric",
-              "year": "2-digit",
-            },
-          },
-          "number": Object {
-            "currency": Object {
-              "style": "currency",
-            },
-            "percent": Object {
-              "style": "percent",
-            },
-          },
-          "relative": Object {
-            "days": Object {
-              "units": "day",
-            },
-            "hours": Object {
-              "units": "hour",
-            },
-            "minutes": Object {
-              "units": "minute",
-            },
-            "months": Object {
-              "units": "month",
-            },
-            "seconds": Object {
-              "units": "second",
-            },
-            "years": Object {
-              "units": "year",
-            },
-          },
-          "time": Object {
-            "full": Object {
-              "hour": "numeric",
-              "minute": "numeric",
-              "second": "numeric",
-              "timeZoneName": "short",
-            },
-            "long": Object {
-              "hour": "numeric",
-              "minute": "numeric",
-              "second": "numeric",
-              "timeZoneName": "short",
-            },
-            "medium": Object {
-              "hour": "numeric",
-              "minute": "numeric",
-              "second": "numeric",
-            },
-            "short": Object {
-              "hour": "numeric",
-              "minute": "numeric",
-            },
-          },
-        }
-      }
-      locale="en"
-      messages={Object {}}
-      textComponent={Symbol(react.fragment)}
-    >
-      <PseudoLocaleWrapper>
-        <EuiPanel
-          paddingSize="none"
-        >
-          <div
-            className="euiPanel"
-          >
-            <div
-              className="discover-table"
-            >
-              <DocTableLegacy
-                columns={
-                  Array [
-                    "_source",
-                  ]
-                }
-                filter={[Function]}
-                hits={
-                  Array [
-                    Object {
-                      "_id": "123",
-                      "_index": "test_index",
-                      "_score": null,
-                      "_source": Object {
-                        "category": Array [
-                          "Men's Clothing",
-                        ],
-                        "currency": "EUR",
-                        "customer_first_name": "Walker",
-                        "customer_full_name": "Walker Texas Ranger",
-                        "customer_gender": "MALE",
-                        "customer_last_name": "Ranger",
-                      },
-                      "_version": 1,
-                      "fields": Array [
-                        Object {
-                          "order_date": Array [
-                            "2020-10-19T13:35:02.000Z",
-                          ],
-                        },
-                      ],
-                      "sort": Array [
-                        1603114502000,
-                        2092,
-                      ],
-                    },
-                  ]
-                }
-                indexPattern={
-                  Object {
-                    "id": "test_index_pattern",
-                  }
-                }
-                infiniteScroll={true}
-                intl={
-                  Object {
-                    "defaultFormats": Object {},
-                    "defaultLocale": "en",
-                    "formatDate": [Function],
-                    "formatHTMLMessage": [Function],
-                    "formatMessage": [Function],
-                    "formatNumber": [Function],
-                    "formatPlural": [Function],
-                    "formatRelative": [Function],
-                    "formatTime": [Function],
-                    "formats": Object {
-                      "date": Object {
-                        "full": Object {
-                          "day": "numeric",
-                          "month": "long",
-                          "weekday": "long",
-                          "year": "numeric",
-                        },
-                        "long": Object {
-                          "day": "numeric",
-                          "month": "long",
-                          "year": "numeric",
-                        },
-                        "medium": Object {
-                          "day": "numeric",
-                          "month": "short",
-                          "year": "numeric",
-                        },
-                        "short": Object {
-                          "day": "numeric",
-                          "month": "numeric",
-                          "year": "2-digit",
-                        },
-                      },
-                      "number": Object {
-                        "currency": Object {
-                          "style": "currency",
-                        },
-                        "percent": Object {
-                          "style": "percent",
-                        },
-                      },
-                      "relative": Object {
-                        "days": Object {
-                          "units": "day",
-                        },
-                        "hours": Object {
-                          "units": "hour",
-                        },
-                        "minutes": Object {
-                          "units": "minute",
-                        },
-                        "months": Object {
-                          "units": "month",
-                        },
-                        "seconds": Object {
-                          "units": "second",
-                        },
-                        "years": Object {
-                          "units": "year",
-                        },
-                      },
-                      "time": Object {
-                        "full": Object {
-                          "hour": "numeric",
-                          "minute": "numeric",
-                          "second": "numeric",
-                          "timeZoneName": "short",
-                        },
-                        "long": Object {
-                          "hour": "numeric",
-                          "minute": "numeric",
-                          "second": "numeric",
-                          "timeZoneName": "short",
-                        },
-                        "medium": Object {
-                          "hour": "numeric",
-                          "minute": "numeric",
-                          "second": "numeric",
-                        },
-                        "short": Object {
-                          "hour": "numeric",
-                          "minute": "numeric",
-                        },
-                      },
-                    },
-                    "formatters": Object {
-                      "getDateTimeFormat": [Function],
-                      "getMessageFormat": [Function],
-                      "getNumberFormat": [Function],
-                      "getPluralFormat": [Function],
-                      "getRelativeFormat": [Function],
-                    },
-                    "locale": "en",
-                    "messages": Object {},
-                    "now": [Function],
-                    "onError": [Function],
-                    "textComponent": Symbol(react.fragment),
-                    "timeZone": null,
-                  }
-                }
-                minimumVisibleRows={5}
-                onFilter={[Function]}
-                rows={
-                  Array [
-                    Object {
-                      "_id": "123",
-                      "_index": "test_index",
-                      "_score": null,
-                      "_source": Object {
-                        "category": Array [
-                          "Men's Clothing",
-                        ],
-                        "currency": "EUR",
-                        "customer_first_name": "Walker",
-                        "customer_full_name": "Walker Texas Ranger",
-                        "customer_gender": "MALE",
-                        "customer_last_name": "Ranger",
-                      },
-                      "_version": 1,
-                      "fields": Array [
-                        Object {
-                          "order_date": Array [
-                            "2020-10-19T13:35:02.000Z",
-                          ],
-                        },
-                      ],
-                      "sort": Array [
-                        1603114502000,
-                        2092,
-                      ],
-                    },
-                  ]
-                }
-                sort={
-                  Array [
-                    Array [
-                      "order_date",
-                    ],
-                    Array [
-                      "desc",
-                    ],
-                  ]
-                }
-                sorting={
-                  Array [
-                    "order_date",
-                    "desc",
-                  ]
-                }
-                status="loaded"
-              >
-                <div />
-              </DocTableLegacy>
-            </div>
-          </div>
-        </EuiPanel>
-      </PseudoLocaleWrapper>
-    </IntlProvider>
-  </I18nProvider>
-</ContextAppLegacy>
-`;
-
-exports[`ContextAppLegacy test renders loading indicator 1`] = `
-<ContextAppLegacy
-  columns={
-    Array [
-      "_source",
-    ]
-  }
-  filter={[Function]}
-  hits={
-    Array [
-      Object {
-        "_id": "123",
-        "_index": "test_index",
-        "_score": null,
-        "_source": Object {
-          "category": Array [
-            "Men's Clothing",
-          ],
-          "currency": "EUR",
-          "customer_first_name": "Walker",
-          "customer_full_name": "Walker Texas Ranger",
-          "customer_gender": "MALE",
-          "customer_last_name": "Ranger",
-        },
-        "_version": 1,
-        "fields": Array [
-          Object {
-            "order_date": Array [
-              "2020-10-19T13:35:02.000Z",
-            ],
-          },
-        ],
-        "sort": Array [
-          1603114502000,
-          2092,
-        ],
-      },
-    ]
-  }
-  indexPattern={
-    Object {
-      "id": "test_index_pattern",
-    }
-  }
-  infiniteScroll={true}
-  intl={
-    Object {
-      "defaultFormats": Object {},
-      "defaultLocale": "en",
-      "formatDate": [Function],
-      "formatHTMLMessage": [Function],
-      "formatMessage": [Function],
-      "formatNumber": [Function],
-      "formatPlural": [Function],
-      "formatRelative": [Function],
-      "formatTime": [Function],
-      "formats": Object {
-        "date": Object {
-          "full": Object {
-            "day": "numeric",
-            "month": "long",
-            "weekday": "long",
-            "year": "numeric",
-          },
-          "long": Object {
-            "day": "numeric",
-            "month": "long",
-            "year": "numeric",
-          },
-          "medium": Object {
-            "day": "numeric",
-            "month": "short",
-            "year": "numeric",
-          },
-          "short": Object {
-            "day": "numeric",
-            "month": "numeric",
-            "year": "2-digit",
-          },
-        },
-        "number": Object {
-          "currency": Object {
-            "style": "currency",
-          },
-          "percent": Object {
-            "style": "percent",
-          },
-        },
-        "relative": Object {
-          "days": Object {
-            "units": "day",
-          },
-          "hours": Object {
-            "units": "hour",
-          },
-          "minutes": Object {
-            "units": "minute",
-          },
-          "months": Object {
-            "units": "month",
-          },
-          "seconds": Object {
-            "units": "second",
-          },
-          "years": Object {
-            "units": "year",
-          },
-        },
-        "time": Object {
-          "full": Object {
-            "hour": "numeric",
-            "minute": "numeric",
-            "second": "numeric",
-            "timeZoneName": "short",
-          },
-          "long": Object {
-            "hour": "numeric",
-            "minute": "numeric",
-            "second": "numeric",
-            "timeZoneName": "short",
-          },
-          "medium": Object {
-            "hour": "numeric",
-            "minute": "numeric",
-            "second": "numeric",
-          },
-          "short": Object {
-            "hour": "numeric",
-            "minute": "numeric",
-          },
-        },
-      },
-      "formatters": Object {
-        "getDateTimeFormat": [Function],
-        "getMessageFormat": [Function],
-        "getNumberFormat": [Function],
-        "getPluralFormat": [Function],
-        "getRelativeFormat": [Function],
-      },
-      "locale": "en",
-      "messages": Object {},
-      "now": [Function],
-      "onError": [Function],
-      "textComponent": Symbol(react.fragment),
-      "timeZone": null,
-    }
-  }
-  minimumVisibleRows={5}
-  sorting={
-    Array [
-      "order_date",
-      "desc",
-    ]
-  }
-  status="loading"
->
-  <I18nProvider>
-    <IntlProvider
-      defaultLocale="en"
-      formats={
-        Object {
-          "date": Object {
-            "full": Object {
-              "day": "numeric",
-              "month": "long",
-              "weekday": "long",
-              "year": "numeric",
-            },
-            "long": Object {
-              "day": "numeric",
-              "month": "long",
-              "year": "numeric",
-            },
-            "medium": Object {
-              "day": "numeric",
-              "month": "short",
-              "year": "numeric",
-            },
-            "short": Object {
-              "day": "numeric",
-              "month": "numeric",
-              "year": "2-digit",
-            },
-          },
-          "number": Object {
-            "currency": Object {
-              "style": "currency",
-            },
-            "percent": Object {
-              "style": "percent",
-            },
-          },
-          "relative": Object {
-            "days": Object {
-              "units": "day",
-            },
-            "hours": Object {
-              "units": "hour",
-            },
-            "minutes": Object {
-              "units": "minute",
-            },
-            "months": Object {
-              "units": "month",
-            },
-            "seconds": Object {
-              "units": "second",
-            },
-            "years": Object {
-              "units": "year",
-            },
-          },
-          "time": Object {
-            "full": Object {
-              "hour": "numeric",
-              "minute": "numeric",
-              "second": "numeric",
-              "timeZoneName": "short",
-            },
-            "long": Object {
-              "hour": "numeric",
-              "minute": "numeric",
-              "second": "numeric",
-              "timeZoneName": "short",
-            },
-            "medium": Object {
-              "hour": "numeric",
-              "minute": "numeric",
-              "second": "numeric",
-            },
-            "short": Object {
-              "hour": "numeric",
-              "minute": "numeric",
-            },
-          },
-        }
-      }
-      locale="en"
-      messages={Object {}}
-      textComponent={Symbol(react.fragment)}
-    >
-      <PseudoLocaleWrapper>
-        <EuiPanel
-          data-test-subj="contextApp_loadingIndicator"
-          paddingSize="l"
-        >
-          <div
-            className="euiPanel euiPanel--paddingLarge"
-            data-test-subj="contextApp_loadingIndicator"
-          >
-            <EuiText
-              textAlign="center"
-            >
-              <div
-                className="euiText euiText--medium"
-              >
-                <EuiTextAlign
-                  textAlign="center"
-                >
-                  <div
-                    className="euiTextAlign euiTextAlign--center"
-                  >
-                    <FormattedMessage
-                      defaultMessage="Loading..."
-                      id="discover.context.loadingDescription"
-                      values={Object {}}
-                    >
-                      Loading...
-                    </FormattedMessage>
-                  </div>
-                </EuiTextAlign>
-              </div>
-            </EuiText>
-          </div>
-        </EuiPanel>
-      </PseudoLocaleWrapper>
-    </IntlProvider>
-  </I18nProvider>
-</ContextAppLegacy>
-`;
diff --git a/src/plugins/discover/public/application/components/context_app/context_app_legacy.test.tsx b/src/plugins/discover/public/application/components/context_app/context_app_legacy.test.tsx
index 16d8cd78004f9..25576a9072944 100644
--- a/src/plugins/discover/public/application/components/context_app/context_app_legacy.test.tsx
+++ b/src/plugins/discover/public/application/components/context_app/context_app_legacy.test.tsx
@@ -23,6 +23,7 @@ import { IIndexPattern } from '../../../../../data/common/index_patterns';
 import { mountWithIntl } from 'test_utils/enzyme_helpers';
 import { DocTableLegacy } from '../../angular/doc_table/create_doc_table_react';
 import { findTestSubject } from '@elastic/eui/lib/test';
+import { ActionBar } from '../../angular/context/components/action_bar/action_bar';
 
 describe('ContextAppLegacy test', () => {
   const hit = {
@@ -48,28 +49,36 @@ describe('ContextAppLegacy test', () => {
     columns: ['_source'],
     filter: () => {},
     hits: [hit],
-    infiniteScroll: true,
     sorting: ['order_date', 'desc'],
     minimumVisibleRows: 5,
     indexPattern,
     status: 'loaded',
+    defaultStepSize: 5,
+    predecessorCount: 10,
+    successorCount: 10,
+    predecessorAvailable: 10,
+    successorAvailable: 10,
+    onChangePredecessorCount: jest.fn(),
+    onChangeSuccessorCount: jest.fn(),
+    predecessorStatus: 'loaded',
+    successorStatus: 'loaded',
   };
 
   it('renders correctly', () => {
     const component = mountWithIntl(<ContextAppLegacy {...defaultProps} />);
-    expect(component).toMatchSnapshot();
     expect(component.find(DocTableLegacy).length).toBe(1);
     const loadingIndicator = findTestSubject(component, 'contextApp_loadingIndicator');
     expect(loadingIndicator.length).toBe(0);
+    expect(component.find(ActionBar).length).toBe(2);
   });
 
   it('renders loading indicator', () => {
     const props = { ...defaultProps };
     props.status = 'loading';
     const component = mountWithIntl(<ContextAppLegacy {...props} />);
-    expect(component).toMatchSnapshot();
     expect(component.find('DocTableLegacy').length).toBe(0);
     const loadingIndicator = findTestSubject(component, 'contextApp_loadingIndicator');
     expect(loadingIndicator.length).toBe(1);
+    expect(component.find(ActionBar).length).toBe(2);
   });
 });
diff --git a/src/plugins/discover/public/application/components/context_app/context_app_legacy.tsx b/src/plugins/discover/public/application/components/context_app/context_app_legacy.tsx
index ee8b2f590f71c..afb4a9a981e21 100644
--- a/src/plugins/discover/public/application/components/context_app/context_app_legacy.tsx
+++ b/src/plugins/discover/public/application/components/context_app/context_app_legacy.tsx
@@ -17,15 +17,15 @@
  * under the License.
  */
 import React from 'react';
-import { FormattedMessage } from '@kbn/i18n/react';
+import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
 import { EuiPanel, EuiText } from '@elastic/eui';
-import { I18nProvider } from '@kbn/i18n/react';
 import {
   DocTableLegacy,
   DocTableLegacyProps,
 } from '../../angular/doc_table/create_doc_table_react';
 import { IIndexPattern, IndexPatternField } from '../../../../../data/common/index_patterns';
 import { LOADING_STATUS } from './constants';
+import { ActionBar, ActionBarProps } from '../../angular/context/components/action_bar/action_bar';
 
 export interface ContextAppProps {
   columns: string[];
@@ -35,15 +35,64 @@ export interface ContextAppProps {
   minimumVisibleRows: number;
   sorting: string[];
   status: string;
+  defaultStepSize: number;
+  predecessorCount: number;
+  successorCount: number;
+  predecessorAvailable: number;
+  successorAvailable: number;
+  onChangePredecessorCount: (count: number) => void;
+  onChangeSuccessorCount: (count: number) => void;
+  predecessorStatus: string;
+  successorStatus: string;
+}
+
+const PREDECESSOR_TYPE = 'predecessors';
+const SUCCESSOR_TYPE = 'successors';
+
+function isLoading(status: string) {
+  return status !== LOADING_STATUS.LOADED && status !== LOADING_STATUS.FAILED;
 }
 
 export function ContextAppLegacy(renderProps: ContextAppProps) {
-  const { hits, filter, sorting, status } = renderProps;
-  const props = ({ ...renderProps } as unknown) as DocTableLegacyProps;
-  props.rows = hits;
-  props.onFilter = filter;
-  props.sort = sorting.map((el) => [el]);
+  const status = renderProps.status;
   const isLoaded = status === LOADING_STATUS.LOADED;
+
+  const actionBarProps = (type: string) => {
+    const {
+      defaultStepSize,
+      successorCount,
+      predecessorCount,
+      predecessorAvailable,
+      successorAvailable,
+      predecessorStatus,
+      successorStatus,
+      onChangePredecessorCount,
+      onChangeSuccessorCount,
+    } = renderProps;
+    const isPredecessorType = type === PREDECESSOR_TYPE;
+    return {
+      defaultStepSize,
+      docCount: isPredecessorType ? predecessorCount : successorCount,
+      docCountAvailable: isPredecessorType ? predecessorAvailable : successorAvailable,
+      onChangeCount: isPredecessorType ? onChangePredecessorCount : onChangeSuccessorCount,
+      isLoading: isPredecessorType ? isLoading(predecessorStatus) : isLoading(successorStatus),
+      type,
+      isDisabled: !isLoaded,
+    } as ActionBarProps;
+  };
+
+  const docTableProps = () => {
+    const { hits, filter, sorting, columns, indexPattern, minimumVisibleRows } = renderProps;
+    return {
+      columns,
+      indexPattern,
+      minimumVisibleRows,
+      rows: hits,
+      onFilter: filter,
+      sort: sorting.map((el) => [el]),
+    } as DocTableLegacyProps;
+  };
+
   const loadingFeedback = () => {
     if (status === LOADING_STATUS.UNINITIALIZED || status === LOADING_STATUS.LOADING) {
       return (
@@ -59,17 +108,20 @@ export function ContextAppLegacy(renderProps: ContextAppProps) {
     }
     return null;
   };
+
   return (
     <I18nProvider>
       <React.Fragment>
+        <ActionBar {...actionBarProps(PREDECESSOR_TYPE)} />
         {loadingFeedback()}
         {isLoaded ? (
           <EuiPanel paddingSize="none">
             <div className="discover-table">
-              <DocTableLegacy {...props} />
+              <DocTableLegacy {...docTableProps()} />
             </div>
           </EuiPanel>
         ) : null}
+        <ActionBar {...actionBarProps(SUCCESSOR_TYPE)} />
       </React.Fragment>
     </I18nProvider>
   );
diff --git a/src/plugins/discover/public/application/components/context_app/context_app_legacy_directive.ts b/src/plugins/discover/public/application/components/context_app/context_app_legacy_directive.ts
index af94c5537da28..4a315be513a0d 100644
--- a/src/plugins/discover/public/application/components/context_app/context_app_legacy_directive.ts
+++ b/src/plugins/discover/public/application/components/context_app/context_app_legacy_directive.ts
@@ -25,8 +25,16 @@ export function createContextAppLegacy(reactDirective: any) {
     ['indexPattern', { watchDepth: 'reference' }],
     ['sorting', { watchDepth: 'reference' }],
     ['columns', { watchDepth: 'collection' }],
-    ['infiniteScroll', { watchDepth: 'reference' }],
     ['minimumVisibleRows', { watchDepth: 'reference' }],
     ['status', { watchDepth: 'reference' }],
+    ['defaultStepSize', { watchDepth: 'reference' }],
+    ['predecessorCount', { watchDepth: 'reference' }],
+    ['predecessorAvailable', { watchDepth: 'reference' }],
+    ['predecessorStatus', { watchDepth: 'reference' }],
+    ['onChangePredecessorCount', { watchDepth: 'reference' }],
+    ['successorCount', { watchDepth: 'reference' }],
+    ['successorAvailable', { watchDepth: 'reference' }],
+    ['successorStatus', { watchDepth: 'reference' }],
+    ['onChangeSuccessorCount', { watchDepth: 'reference' }],
   ]);
 }
diff --git a/src/plugins/embeddable/public/lib/panel/_embeddable_panel.scss b/src/plugins/embeddable/public/lib/panel/_embeddable_panel.scss
index cdc0f9f0e0451..6b8654f6c3528 100644
--- a/src/plugins/embeddable/public/lib/panel/_embeddable_panel.scss
+++ b/src/plugins/embeddable/public/lib/panel/_embeddable_panel.scss
@@ -64,12 +64,12 @@
 
   .embPanel__titleText {
     @include euiTextTruncate;
+    font-weight: $euiFontWeightBold;
   }
 
   .embPanel__placeholderTitleText {
-    @include euiTextTruncate;
-    font-weight: $euiFontWeightRegular;
     color: $euiColorMediumShade;
+    font-weight: $euiFontWeightRegular;
   }
 }
 
diff --git a/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx b/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx
index fcf79c1d6b211..c717e4370231e 100644
--- a/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx
+++ b/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx
@@ -19,7 +19,7 @@
 
 import React from 'react';
 import { mount } from 'enzyme';
-import { nextTick } from 'test_utils/enzyme_helpers';
+import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers';
 
 import { findTestSubject } from '@elastic/eui/lib/test';
 import { I18nProvider } from '@kbn/i18n/react';
@@ -343,6 +343,88 @@ test('HelloWorldContainer in edit mode shows edit mode actions', async () => {
   // expect(action.length).toBe(1);
 });
 
+test('Panel title customize link does not exist in view mode', async () => {
+  const inspector = inspectorPluginMock.createStartContract();
+
+  const container = new HelloWorldContainer(
+    { id: '123', panels: {}, viewMode: ViewMode.VIEW, hidePanelTitles: false },
+    { getEmbeddableFactory } as any
+  );
+
+  const embeddable = await container.addNewEmbeddable<
+    ContactCardEmbeddableInput,
+    ContactCardEmbeddableOutput,
+    ContactCardEmbeddable
+  >(CONTACT_CARD_EMBEDDABLE, {
+    firstName: 'Vayon',
+    lastName: 'Poole',
+  });
+
+  const component = mountWithIntl(
+    <EmbeddablePanel
+      embeddable={embeddable}
+      getActions={() => Promise.resolve([])}
+      getAllEmbeddableFactories={start.getEmbeddableFactories}
+      getEmbeddableFactory={start.getEmbeddableFactory}
+      notifications={{} as any}
+      overlays={{} as any}
+      application={applicationMock}
+      inspector={inspector}
+      SavedObjectFinder={() => null}
+    />
+  );
+
+  const titleLink = findTestSubject(component, 'embeddablePanelTitleLink');
+  expect(titleLink.length).toBe(0);
+});
+
+test('Runs customize panel action on title click when in edit mode', async () => {
+  const inspector = inspectorPluginMock.createStartContract();
+
+  const container = new HelloWorldContainer(
+    { id: '123', panels: {}, viewMode: ViewMode.EDIT, hidePanelTitles: false },
+    { getEmbeddableFactory } as any
+  );
+
+  const embeddable = await container.addNewEmbeddable<
+    ContactCardEmbeddableInput,
+    ContactCardEmbeddableOutput,
+    ContactCardEmbeddable
+  >(CONTACT_CARD_EMBEDDABLE, {
+    firstName: 'Vayon',
+    lastName: 'Poole',
+  });
+
+  const component = mountWithIntl(
+    <EmbeddablePanel
+      embeddable={embeddable}
+      getActions={() => Promise.resolve([])}
+      getAllEmbeddableFactories={start.getEmbeddableFactories}
+      getEmbeddableFactory={start.getEmbeddableFactory}
+      notifications={{} as any}
+      overlays={{} as any}
+      application={applicationMock}
+      inspector={inspector}
+      SavedObjectFinder={() => null}
+    />
+  );
+
+  const titleExecute = jest.fn();
+  component.setState((s: any) => ({
+    ...s,
+    universalActions: {
+      ...s.universalActions,
+      customizePanelTitle: { execute: titleExecute, isCompatible: jest.fn() },
+    },
+  }));
+
+  const titleLink = findTestSubject(component, 'embeddablePanelTitleLink');
+  expect(titleLink.length).toBe(1);
+  titleLink.simulate('click');
+  await nextTick();
+  expect(titleExecute).toHaveBeenCalledTimes(1);
+});
+
 test('Updates when hidePanelTitles is toggled', async () => {
   const inspector = inspectorPluginMock.createStartContract();
 
diff --git a/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx b/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx
index 137f8c24b1fae..1cd48e85469fd 100644
--- a/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx
+++ b/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx
@@ -76,6 +76,7 @@ interface Props {
 
 interface State {
   panels: EuiContextMenuPanelDescriptor[];
+  universalActions: PanelUniversalActions;
   focusedPanelIndex?: string;
   viewMode: ViewMode;
   hidePanelTitle: boolean;
@@ -86,6 +87,14 @@ interface State {
   error?: EmbeddableError;
 }
 
+interface PanelUniversalActions {
+  customizePanelTitle: CustomizePanelTitleAction;
+  addPanel: AddPanelAction;
+  inspectPanel: InspectPanelAction;
+  removePanel: RemovePanelAction;
+  editPanel: EditPanelAction;
+}
+
 export class EmbeddablePanel extends React.Component<Props, State> {
   private embeddableRoot: React.RefObject<HTMLDivElement>;
   private parentSubscription?: Subscription;
@@ -102,6 +111,7 @@ export class EmbeddablePanel extends React.Component<Props, State> {
       Boolean(embeddable.getInput()?.hidePanelTitles);
 
     this.state = {
+      universalActions: this.getUniversalActions(),
       panels: [],
       viewMode,
       hidePanelTitle,
@@ -229,6 +239,7 @@ export class EmbeddablePanel extends React.Component<Props, State> {
             getActionContextMenuPanel={this.getActionContextMenuPanel}
             hidePanelTitle={this.state.hidePanelTitle}
             isViewMode={viewOnlyMode}
+            customizeTitle={this.state.universalActions.customizePanelTitle}
             closeContextMenu={this.state.closeContextMenu}
             title={title}
             badges={this.state.badges}
@@ -267,17 +278,7 @@ export class EmbeddablePanel extends React.Component<Props, State> {
     }
   };
 
-  private getActionContextMenuPanel = async () => {
-    let regularActions = await this.props.getActions(CONTEXT_MENU_TRIGGER, {
-      embeddable: this.props.embeddable,
-    });
-
-    const { disabledActions } = this.props.embeddable.getInput();
-    if (disabledActions) {
-      const removeDisabledActions = removeById(disabledActions);
-      regularActions = regularActions.filter(removeDisabledActions);
-    }
-
+  private getUniversalActions = (): PanelUniversalActions => {
     const createGetUserData = (overlays: OverlayStart) =>
       async function getUserData(context: { embeddable: IEmbeddable }) {
         return new Promise<{ title: string | undefined; hideTitle?: boolean }>((resolve) => {
@@ -299,27 +300,41 @@ export class EmbeddablePanel extends React.Component<Props, State> {
         });
       };
 
-    // These actions are exposed on the context menu for every embeddable, they bypass the trigger
+    // Universal actions are exposed on the context menu for every embeddable, they bypass the trigger
     // registry.
-    const extraActions: Array<Action<EmbeddableContext>> = [
-      new CustomizePanelTitleAction(createGetUserData(this.props.overlays)),
-      new AddPanelAction(
+    return {
+      customizePanelTitle: new CustomizePanelTitleAction(createGetUserData(this.props.overlays)),
+      addPanel: new AddPanelAction(
         this.props.getEmbeddableFactory,
         this.props.getAllEmbeddableFactories,
         this.props.overlays,
         this.props.notifications,
         this.props.SavedObjectFinder
       ),
-      new InspectPanelAction(this.props.inspector),
-      new RemovePanelAction(),
-      new EditPanelAction(
+      inspectPanel: new InspectPanelAction(this.props.inspector),
+      removePanel: new RemovePanelAction(),
+      editPanel: new EditPanelAction(
         this.props.getEmbeddableFactory,
         this.props.application,
         this.props.stateTransfer
       ),
-    ];
+    };
+  };
 
-    const sortedActions = [...regularActions, ...extraActions].sort(sortByOrderField);
+  private getActionContextMenuPanel = async () => {
+    let regularActions = await this.props.getActions(CONTEXT_MENU_TRIGGER, {
+      embeddable: this.props.embeddable,
+    });
+
+    const { disabledActions } = this.props.embeddable.getInput();
+    if (disabledActions) {
+      const removeDisabledActions = removeById(disabledActions);
+      regularActions = regularActions.filter(removeDisabledActions);
+    }
+
+    const sortedActions = [...regularActions, ...Object.values(this.state.universalActions)].sort(
+      sortByOrderField
+    );
 
     return await buildContextMenuForActions({
       actions: sortedActions.map((action) => ({
diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_header.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_header.tsx
index 9bcef051a9359..44f5c3df2709d 100644
--- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_header.tsx
+++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_header.tsx
@@ -24,6 +24,7 @@ import {
   EuiToolTip,
   EuiScreenReaderOnly,
   EuiNotificationBadge,
+  EuiLink,
 } from '@elastic/eui';
 import classNames from 'classnames';
 import React from 'react';
@@ -32,6 +33,7 @@ import { PanelOptionsMenu } from './panel_options_menu';
 import { IEmbeddable } from '../../embeddables';
 import { EmbeddableContext, panelBadgeTrigger, panelNotificationTrigger } from '../../triggers';
 import { uiToReactComponent } from '../../../../../kibana_react/public';
+import { CustomizePanelTitleAction } from '.';
 
 export interface PanelHeaderProps {
   title?: string;
@@ -44,6 +46,7 @@ export interface PanelHeaderProps {
   embeddable: IEmbeddable;
   headerId?: string;
   showPlaceholderTitle?: boolean;
+  customizeTitle: CustomizePanelTitleAction;
 }
 
 function renderBadges(badges: Array<Action<EmbeddableContext>>, embeddable: IEmbeddable) {
@@ -129,6 +132,7 @@ export function PanelHeader({
   notifications,
   embeddable,
   headerId,
+  customizeTitle,
 }: PanelHeaderProps) {
   const description = getViewDescription(embeddable);
   const showTitle = !hidePanelTitle && (!isViewMode || title);
@@ -172,11 +176,35 @@ export function PanelHeader({
   }
 
   const renderTitle = () => {
-    const titleComponent = showTitle ? (
-      <span className={title ? 'embPanel__titleText' : 'embPanel__placeholderTitleText'}>
-        {title || placeholderTitle}
-      </span>
-    ) : undefined;
+    let titleComponent;
+    if (showTitle) {
+      titleComponent = isViewMode ? (
+        <span
+          className={classNames('embPanel__titleText', {
+            // eslint-disable-next-line @typescript-eslint/naming-convention
+            embPanel__placeholderTitleText: !title,
+          })}
+        >
+          {title || placeholderTitle}
+        </span>
+      ) : (
+        <EuiLink
+          color="text"
+          data-test-subj={'embeddablePanelTitleLink'}
+          className={classNames('embPanel__titleText', {
+            // eslint-disable-next-line @typescript-eslint/naming-convention
+            embPanel__placeholderTitleText: !title,
+          })}
+          aria-label={i18n.translate('embeddableApi.panel.editTitleAriaLabel', {
+            defaultMessage: 'Click to edit title: {title}',
+            values: { title: title || placeholderTitle },
+          })}
+          onClick={() => customizeTitle.execute({ embeddable })}
+        >
+          {title || placeholderTitle}
+        </EuiLink>
+      );
+    }
     return description ? (
       <EuiToolTip
         content={description}
diff --git a/src/plugins/embeddable/public/public.api.md b/src/plugins/embeddable/public/public.api.md
index a6d90f2766c18..84dd97c8288fc 100644
--- a/src/plugins/embeddable/public/public.api.md
+++ b/src/plugins/embeddable/public/public.api.md
@@ -71,6 +71,7 @@ import { SearchResponse } from 'elasticsearch';
 import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/common';
 import { ShallowPromise } from '@kbn/utility-types';
 import { SimpleSavedObject as SimpleSavedObject_2 } from 'src/core/public';
+import { Start as Start_2 } from 'src/plugins/inspector/public';
 import { ToastInputFields as ToastInputFields_2 } from 'src/core/public/notifications';
 import { ToastsSetup as ToastsSetup_2 } from 'kibana/public';
 import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport';
diff --git a/src/plugins/expressions/common/execution/execution.abortion.test.ts b/src/plugins/expressions/common/execution/execution.abortion.test.ts
index ecbf94eceae64..9fa7d92875b9a 100644
--- a/src/plugins/expressions/common/execution/execution.abortion.test.ts
+++ b/src/plugins/expressions/common/execution/execution.abortion.test.ts
@@ -36,8 +36,7 @@ const createExecution = (
   const execution = new Execution({
     executor,
     ast: parseExpression(expression),
-    context,
-    debug,
+    params: { ...context, debug },
   });
   return execution;
 };
diff --git a/src/plugins/expressions/common/execution/execution.test.ts b/src/plugins/expressions/common/execution/execution.test.ts
index ff331d7c5ddaf..3bd29632f0902 100644
--- a/src/plugins/expressions/common/execution/execution.test.ts
+++ b/src/plugins/expressions/common/execution/execution.test.ts
@@ -38,8 +38,10 @@ const createExecution = (
   const execution = new Execution({
     executor,
     ast: parseExpression(expression),
-    context,
-    debug,
+    params: {
+      ...context,
+      debug,
+    },
   });
   return execution;
 };
@@ -68,7 +70,7 @@ describe('Execution', () => {
   test('creates default ExecutionContext', () => {
     const execution = createExecution();
     expect(execution.context).toMatchObject({
-      getInitialInput: expect.any(Function),
+      getSearchContext: expect.any(Function),
       variables: expect.any(Object),
       types: expect.any(Object),
     });
@@ -143,6 +145,7 @@ describe('Execution', () => {
       const execution = new Execution({
         executor,
         expression,
+        params: {},
       });
       expect(execution.expression).toBe(expression);
     });
@@ -153,6 +156,7 @@ describe('Execution', () => {
       const execution = new Execution({
         ast: parseExpression(expression),
         executor,
+        params: {},
       });
       expect(execution.expression).toBe(expression);
     });
@@ -619,7 +623,7 @@ describe('Execution', () => {
         const execution = new Execution({
           executor,
           ast: parseExpression('add val=1 | throws | add val=3'),
-          debug: true,
+          params: { debug: true },
         });
         execution.start(0);
         await execution.result;
@@ -637,7 +641,7 @@ describe('Execution', () => {
         const execution = new Execution({
           executor,
           ast: parseExpression('add val=1 | throws | add val=3'),
-          debug: true,
+          params: { debug: true },
         });
         execution.start(0);
         await execution.result;
@@ -658,7 +662,7 @@ describe('Execution', () => {
         const execution = new Execution({
           executor,
           ast: parseExpression('add val=1 | throws | add val=3'),
-          debug: true,
+          params: { debug: true },
         });
         execution.start(0);
         await execution.result;
diff --git a/src/plugins/expressions/common/execution/execution.ts b/src/plugins/expressions/common/execution/execution.ts
index 69140453f486d..2bcf441b14203 100644
--- a/src/plugins/expressions/common/execution/execution.ts
+++ b/src/plugins/expressions/common/execution/execution.ts
@@ -19,7 +19,7 @@
 
 import { i18n } from '@kbn/i18n';
 import { keys, last, mapValues, reduce, zipObject } from 'lodash';
-import { Executor, ExpressionExecOptions } from '../executor';
+import { Executor } from '../executor';
 import { createExecutionContainer, ExecutionContainer } from './container';
 import { createError } from '../util';
 import { Defer, now } from '../../../kibana_utils/common';
@@ -39,6 +39,7 @@ import { getType, ExpressionValue } from '../expression_types';
 import { ArgumentType, ExpressionFunction } from '../expression_functions';
 import { getByAlias } from '../util/get_by_alias';
 import { ExecutionContract } from './execution_contract';
+import { ExpressionExecutionParams } from '../service';
 
 const createAbortErrorValue = () =>
   createError({
@@ -46,20 +47,11 @@ const createAbortErrorValue = () =>
     name: 'AbortError',
   });
 
-export interface ExecutionParams<
-  ExtraContext extends Record<string, unknown> = Record<string, unknown>
-> {
+export interface ExecutionParams {
   executor: Executor<any>;
   ast?: ExpressionAstExpression;
   expression?: string;
-  context?: ExtraContext;
-
-  /**
-   * Whether to execute expression in *debug mode*. In *debug mode* inputs and
-   * outputs as well as all resolved arguments and time it took to execute each
-   * function are saved and are available for introspection.
-   */
-  debug?: boolean;
+  params: ExpressionExecutionParams;
 }
 
 const createDefaultInspectorAdapters = (): DefaultInspectorAdapters => ({
@@ -68,11 +60,10 @@ const createDefaultInspectorAdapters = (): DefaultInspectorAdapters => ({
 });
 
 export class Execution<
-  ExtraContext extends Record<string, unknown> = Record<string, unknown>,
   Input = unknown,
   Output = unknown,
-  InspectorAdapters extends Adapters = ExtraContext['inspectorAdapters'] extends object
-    ? ExtraContext['inspectorAdapters']
+  InspectorAdapters extends Adapters = ExpressionExecutionParams['inspectorAdapters'] extends object
+    ? ExpressionExecutionParams['inspectorAdapters']
     : DefaultInspectorAdapters
 > {
   /**
@@ -92,7 +83,7 @@ export class Execution<
    * Execution context - object that allows to do side-effects. Context is passed
    * to every function.
    */
-  public readonly context: ExecutionContext<Input, InspectorAdapters> & ExtraContext;
+  public readonly context: ExecutionContext<InspectorAdapters>;
 
   /**
    * AbortController to cancel this Execution.
@@ -126,11 +117,10 @@ export class Execution<
    * can return to other plugins for their consumption.
    */
   public readonly contract: ExecutionContract<
-    ExtraContext,
     Input,
     Output,
     InspectorAdapters
-  > = new ExecutionContract<ExtraContext, Input, Output, InspectorAdapters>(this);
+  > = new ExecutionContract<Input, Output, InspectorAdapters>(this);
 
   public readonly expression: string;
 
@@ -142,17 +132,17 @@ export class Execution<
     return this.context.inspectorAdapters;
   }
 
-  constructor(public readonly params: ExecutionParams<ExtraContext>) {
-    const { executor } = params;
+  constructor(public readonly execution: ExecutionParams) {
+    const { executor } = execution;
 
-    if (!params.ast && !params.expression) {
+    if (!execution.ast && !execution.expression) {
       throw new TypeError('Execution params should contain at least .ast or .expression key.');
-    } else if (params.ast && params.expression) {
+    } else if (execution.ast && execution.expression) {
       throw new TypeError('Execution params cannot contain both .ast and .expression key.');
     }
 
-    this.expression = params.expression || formatExpression(params.ast!);
-    const ast = params.ast || parseExpression(this.expression);
+    this.expression = execution.expression || formatExpression(execution.ast!);
+    const ast = execution.ast || parseExpression(this.expression);
 
     this.state = createExecutionContainer<Output | ExpressionValueError>({
       ...executor.state.get(),
@@ -161,14 +151,13 @@ export class Execution<
     });
 
     this.context = {
-      getInitialInput: () => this.input,
-      variables: {},
+      getSearchContext: () => this.execution.params.searchContext || {},
+      getSearchSessionId: () => execution.params.searchSessionId,
+      variables: execution.params.variables || {},
       types: executor.getTypes(),
       abortSignal: this.abortController.signal,
-      ...(params.context || ({} as ExtraContext)),
-      inspectorAdapters: (params.context && params.context.inspectorAdapters
-        ? params.context.inspectorAdapters
-        : createDefaultInspectorAdapters()) as InspectorAdapters,
+      inspectorAdapters: execution.params.inspectorAdapters || createDefaultInspectorAdapters(),
+      ...(execution.params as any).extraContext,
     };
   }
 
@@ -249,10 +238,10 @@ export class Execution<
         // actually have a `then` function which would be treated as a `Promise`.
         const { resolvedArgs } = await this.race(this.resolveArgs(fn, input, fnArgs));
         args = resolvedArgs;
-        timeStart = this.params.debug ? now() : 0;
+        timeStart = this.execution.params.debug ? now() : 0;
         const output = await this.race(this.invokeFunction(fn, input, resolvedArgs));
 
-        if (this.params.debug) {
+        if (this.execution.params.debug) {
           const timeEnd: number = now();
           (link as ExpressionAstFunction).debug = {
             success: true,
@@ -267,11 +256,11 @@ export class Execution<
         if (getType(output) === 'error') return output;
         input = output;
       } catch (rawError) {
-        const timeEnd: number = this.params.debug ? now() : 0;
+        const timeEnd: number = this.execution.params.debug ? now() : 0;
         const error = createError(rawError) as ExpressionValueError;
         error.error.message = `[${fnName}] > ${error.error.message}`;
 
-        if (this.params.debug) {
+        if (this.execution.params.debug) {
           (link as ExpressionAstFunction).debug = {
             success: false,
             fn: fn.name,
@@ -404,9 +393,7 @@ export class Execution<
     const resolveArgFns = mapValues(argAstsWithDefaults, (asts, argName) => {
       return asts.map((item: ExpressionAstExpression) => {
         return async (subInput = input) => {
-          const output = await this.interpret(item, subInput, {
-            debug: this.params.debug,
-          });
+          const output = await this.interpret(item, subInput);
           if (isExpressionValueError(output)) throw output.error;
           const casted = this.cast(output, argDefs[argName as any].types);
           return casted;
@@ -438,17 +425,12 @@ export class Execution<
     return { resolvedArgs };
   }
 
-  public async interpret<T>(
-    ast: ExpressionAstNode,
-    input: T,
-    options?: ExpressionExecOptions
-  ): Promise<unknown> {
+  public async interpret<T>(ast: ExpressionAstNode, input: T): Promise<unknown> {
     switch (getType(ast)) {
       case 'expression':
-        const execution = this.params.executor.createExecution(
+        const execution = this.execution.executor.createExecution(
           ast as ExpressionAstExpression,
-          this.context,
-          options
+          this.execution.params
         );
         execution.start(input);
         return await execution.result;
diff --git a/src/plugins/expressions/common/execution/execution_contract.test.ts b/src/plugins/expressions/common/execution/execution_contract.test.ts
index c33f8a1a0f36e..856b22470d782 100644
--- a/src/plugins/expressions/common/execution/execution_contract.test.ts
+++ b/src/plugins/expressions/common/execution/execution_contract.test.ts
@@ -30,7 +30,7 @@ const createExecution = (
   const execution = new Execution({
     executor,
     ast: parseExpression(expression),
-    context,
+    params: { ...context },
   });
   return execution;
 };
diff --git a/src/plugins/expressions/common/execution/execution_contract.ts b/src/plugins/expressions/common/execution/execution_contract.ts
index 79bb4c58ab48d..f05f1ded82799 100644
--- a/src/plugins/expressions/common/execution/execution_contract.ts
+++ b/src/plugins/expressions/common/execution/execution_contract.ts
@@ -25,21 +25,14 @@ import { ExpressionAstExpression } from '../ast';
  * `ExecutionContract` is a wrapper around `Execution` class. It provides the
  * same functionality but does not expose Expressions plugin internals.
  */
-export class ExecutionContract<
-  ExtraContext extends Record<string, unknown> = Record<string, unknown>,
-  Input = unknown,
-  Output = unknown,
-  InspectorAdapters = unknown
-> {
+export class ExecutionContract<Input = unknown, Output = unknown, InspectorAdapters = unknown> {
   public get isPending(): boolean {
     const state = this.execution.state.get().state;
     const finished = state === 'error' || state === 'result';
     return !finished;
   }
 
-  constructor(
-    protected readonly execution: Execution<ExtraContext, Input, Output, InspectorAdapters>
-  ) {}
+  constructor(protected readonly execution: Execution<Input, Output, InspectorAdapters>) {}
 
   /**
    * Cancel the execution of the expression. This will set abort signal
diff --git a/src/plugins/expressions/common/execution/types.ts b/src/plugins/expressions/common/execution/types.ts
index 7c26e586fb790..50475c3bd94ae 100644
--- a/src/plugins/expressions/common/execution/types.ts
+++ b/src/plugins/expressions/common/execution/types.ts
@@ -26,11 +26,11 @@ import { SavedObject, SavedObjectAttributes } from '../../../../core/public';
  * `ExecutionContext` is an object available to all functions during a single execution;
  * it provides various methods to perform side-effects.
  */
-export interface ExecutionContext<Input = unknown, InspectorAdapters extends Adapters = Adapters> {
+export interface ExecutionContext<InspectorAdapters extends Adapters = Adapters> {
   /**
-   * Get initial input with which execution started.
+   * Get search context of the expression.
    */
-  getInitialInput: () => Input;
+  getSearchContext: () => ExecutionContextSearch;
 
   /**
    * Context variables that can be consumed using `var` and `var_set` functions.
@@ -55,7 +55,7 @@ export interface ExecutionContext<Input = unknown, InspectorAdapters extends Ada
   /**
    * Search context in which expression should operate.
    */
-  search?: ExecutionContextSearch;
+  getSearchSessionId: () => string | undefined;
 
   /**
    * Allows to fetch saved objects from ElasticSearch. In browser `getSavedObject`
diff --git a/src/plugins/expressions/common/executor/executor.ts b/src/plugins/expressions/common/executor/executor.ts
index fd7f5808f0340..85b5589b593af 100644
--- a/src/plugins/expressions/common/executor/executor.ts
+++ b/src/plugins/expressions/common/executor/executor.ts
@@ -33,6 +33,7 @@ import { functionSpecs } from '../expression_functions/specs';
 import { getByAlias } from '../util';
 import { SavedObjectReference } from '../../../../core/types';
 import { PersistableState } from '../../../kibana_utils/common';
+import { ExpressionExecutionParams } from '../service';
 
 export interface ExpressionExecOptions {
   /**
@@ -166,43 +167,34 @@ export class Executor<Context extends Record<string, unknown> = Record<string, u
    * @param context Extra global context object that will be merged into the
    *    expression global context object that is provided to each function to allow side-effects.
    */
-  public async run<
-    Input,
-    Output,
-    ExtraContext extends Record<string, unknown> = Record<string, unknown>
-  >(
+  public async run<Input, Output>(
     ast: string | ExpressionAstExpression,
     input: Input,
-    context?: ExtraContext,
-    options?: ExpressionExecOptions
+    params: ExpressionExecutionParams = {}
   ) {
-    const execution = this.createExecution(ast, context, options);
+    const execution = this.createExecution(ast, params);
     execution.start(input);
     return (await execution.result) as Output;
   }
 
-  public createExecution<
-    ExtraContext extends Record<string, unknown> = Record<string, unknown>,
-    Input = unknown,
-    Output = unknown
-  >(
+  public createExecution<Input = unknown, Output = unknown>(
     ast: string | ExpressionAstExpression,
-    context: ExtraContext = {} as ExtraContext,
-    { debug }: ExpressionExecOptions = {} as ExpressionExecOptions
-  ): Execution<Context & ExtraContext, Input, Output> {
-    const params: ExecutionParams<Context & ExtraContext> = {
+    params: ExpressionExecutionParams = {}
+  ): Execution<Input, Output> {
+    const executionParams: ExecutionParams = {
       executor: this,
-      context: {
-        ...this.context,
-        ...context,
-      } as Context & ExtraContext,
-      debug,
+      params: {
+        ...params,
+        // for canvas we are passing this in,
+        // canvas should be refactored to not pass any extra context in
+        extraContext: this.context,
+      } as any,
     };
 
-    if (typeof ast === 'string') params.expression = ast;
-    else params.ast = ast;
+    if (typeof ast === 'string') executionParams.expression = ast;
+    else executionParams.ast = ast;
 
-    const execution = new Execution<Context & ExtraContext, Input, Output>(params);
+    const execution = new Execution<Input, Output>(executionParams);
 
     return execution;
   }
diff --git a/src/plugins/expressions/common/expression_functions/specs/kibana.ts b/src/plugins/expressions/common/expression_functions/specs/kibana.ts
index 2144a8aba2d19..3ec4c23eab28d 100644
--- a/src/plugins/expressions/common/expression_functions/specs/kibana.ts
+++ b/src/plugins/expressions/common/expression_functions/specs/kibana.ts
@@ -44,15 +44,15 @@ export const kibana: ExpressionFunctionKibana = {
 
   args: {},
 
-  fn(input, _, { search = {} }) {
+  fn(input, _, { getSearchContext }) {
     const output: ExpressionValueSearchContext = {
       // TODO: This spread is left here for legacy reasons, possibly Lens uses it.
       // TODO: But it shouldn't be need.
       ...input,
       type: 'kibana_context',
-      query: [...toArray(search.query), ...toArray((input || {}).query)],
-      filters: [...(search.filters || []), ...((input || {}).filters || [])],
-      timeRange: search.timeRange || (input ? input.timeRange : undefined),
+      query: [...toArray(getSearchContext().query), ...toArray((input || {}).query)],
+      filters: [...(getSearchContext().filters || []), ...((input || {}).filters || [])],
+      timeRange: getSearchContext().timeRange || (input ? input.timeRange : undefined),
     };
 
     return output;
diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/kibana.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/kibana.test.ts
index e5bd53f63c91d..e5c4b92de4fdb 100644
--- a/src/plugins/expressions/common/expression_functions/specs/tests/kibana.test.ts
+++ b/src/plugins/expressions/common/expression_functions/specs/tests/kibana.test.ts
@@ -46,8 +46,8 @@ describe('interpreter/functions#kibana', () => {
       timeRange: { from: '2', to: '3' },
     };
     context = {
-      search,
-      getInitialInput: () => input,
+      getSearchContext: () => search,
+      getSearchSessionId: () => undefined,
       types: {},
       variables: {},
       abortSignal: {} as any,
diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts
index 263409f0caca2..88511d4fd571e 100644
--- a/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts
+++ b/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts
@@ -37,7 +37,8 @@ describe('expression_functions', () => {
       };
 
       context = {
-        getInitialInput: () => {},
+        getSearchContext: () => ({} as any),
+        getSearchSessionId: () => undefined,
         types: {},
         variables: { theme: themeProps },
         abortSignal: {} as any,
diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/var.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/var.test.ts
index ccf49ec918d3d..762f34e3f5566 100644
--- a/src/plugins/expressions/common/expression_functions/specs/tests/var.test.ts
+++ b/src/plugins/expressions/common/expression_functions/specs/tests/var.test.ts
@@ -31,7 +31,8 @@ describe('expression_functions', () => {
     beforeEach(() => {
       input = { timeRange: { from: '0', to: '1' } };
       context = {
-        getInitialInput: () => input,
+        getSearchContext: () => input,
+        getSearchSessionId: () => undefined,
         types: {},
         variables: { test: 1 },
         abortSignal: {} as any,
diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/var_set.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/var_set.test.ts
index b1ae44e6f899e..365ae5b89baea 100644
--- a/src/plugins/expressions/common/expression_functions/specs/tests/var_set.test.ts
+++ b/src/plugins/expressions/common/expression_functions/specs/tests/var_set.test.ts
@@ -32,7 +32,8 @@ describe('expression_functions', () => {
     beforeEach(() => {
       input = { timeRange: { from: '0', to: '1' } };
       context = {
-        getInitialInput: () => input,
+        getSearchContext: () => input,
+        getSearchSessionId: () => undefined,
         types: {},
         variables: { test: 1 },
         abortSignal: {} as any,
diff --git a/src/plugins/expressions/common/mocks.ts b/src/plugins/expressions/common/mocks.ts
index 502d88ac955ae..52f96953885cf 100644
--- a/src/plugins/expressions/common/mocks.ts
+++ b/src/plugins/expressions/common/mocks.ts
@@ -23,7 +23,8 @@ export const createMockExecutionContext = <ExtraContext extends object = object>
   extraContext: ExtraContext = {} as ExtraContext
 ): ExecutionContext & ExtraContext => {
   const executionContext: ExecutionContext = {
-    getInitialInput: jest.fn(),
+    getSearchContext: jest.fn(),
+    getSearchSessionId: jest.fn(),
     variables: {},
     types: {},
     abortSignal: {
@@ -37,7 +38,6 @@ export const createMockExecutionContext = <ExtraContext extends object = object>
       requests: {} as any,
       data: {} as any,
     },
-    search: {},
   };
 
   return {
diff --git a/src/plugins/expressions/common/service/expressions_services.ts b/src/plugins/expressions/common/service/expressions_services.ts
index 3d0fb968e8a3a..abbba433ab3ca 100644
--- a/src/plugins/expressions/common/service/expressions_services.ts
+++ b/src/plugins/expressions/common/service/expressions_services.ts
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import { Executor, ExpressionExecOptions } from '../executor';
+import { Executor } from '../executor';
 import { AnyExpressionRenderDefinition, ExpressionRendererRegistry } from '../expression_renderers';
 import { ExpressionAstExpression } from '../ast';
 import { ExecutionContract } from '../execution/execution_contract';
@@ -25,6 +25,8 @@ import { AnyExpressionTypeDefinition } from '../expression_types';
 import { AnyExpressionFunctionDefinition } from '../expression_functions';
 import { SavedObjectReference } from '../../../../core/types';
 import { PersistableState } from '../../../kibana_utils/common';
+import { Adapters } from '../../../inspector/common/adapters';
+import { ExecutionContextSearch } from '../execution';
 
 /**
  * The public contract that `ExpressionsService` provides to other plugins
@@ -45,6 +47,23 @@ export type ExpressionsServiceSetup = Pick<
   | 'fork'
 >;
 
+export interface ExpressionExecutionParams {
+  searchContext?: ExecutionContextSearch;
+
+  variables?: Record<string, any>;
+
+  /**
+   * Whether to execute expression in *debug mode*. In *debug mode* inputs and
+   * outputs as well as all resolved arguments and time it took to execute each
+   * function are saved and are available for introspection.
+   */
+  debug?: boolean;
+
+  searchSessionId?: string;
+
+  inspectorAdapters?: Adapters;
+}
+
 /**
  * The public contract that `ExpressionsService` provides to other plugins
  * in Kibana Platform in *start* life-cycle.
@@ -98,11 +117,10 @@ export interface ExpressionsServiceStart {
    * expressions.run('...', null, { elasticsearchClient });
    * ```
    */
-  run: <Input, Output, ExtraContext extends Record<string, unknown> = Record<string, unknown>>(
+  run: <Input, Output>(
     ast: string | ExpressionAstExpression,
     input: Input,
-    context?: ExtraContext,
-    options?: ExpressionExecOptions
+    params?: ExpressionExecutionParams
   ) => Promise<Output>;
 
   /**
@@ -110,17 +128,12 @@ export interface ExpressionsServiceStart {
    * instance that tracks the progress of the execution and can be used to
    * interact with the execution.
    */
-  execute: <
-    Input = unknown,
-    Output = unknown,
-    ExtraContext extends Record<string, unknown> = Record<string, unknown>
-  >(
+  execute: <Input = unknown, Output = unknown>(
     ast: string | ExpressionAstExpression,
     // This any is for legacy reasons.
     input: Input,
-    context?: ExtraContext,
-    options?: ExpressionExecOptions
-  ) => ExecutionContract<ExtraContext, Input, Output>;
+    params?: ExpressionExecutionParams
+  ) => ExecutionContract<Input, Output>;
 
   /**
    * Create a new instance of `ExpressionsService`. The new instance inherits
@@ -214,8 +227,8 @@ export class ExpressionsService implements PersistableState<ExpressionAstExpress
     definition: AnyExpressionRenderDefinition | (() => AnyExpressionRenderDefinition)
   ): void => this.renderers.register(definition);
 
-  public readonly run: ExpressionsServiceStart['run'] = (ast, input, context, options) =>
-    this.executor.run(ast, input, context, options);
+  public readonly run: ExpressionsServiceStart['run'] = (ast, input, params) =>
+    this.executor.run(ast, input, params);
 
   public readonly getFunction: ExpressionsServiceStart['getFunction'] = (name) =>
     this.executor.getFunction(name);
@@ -246,8 +259,8 @@ export class ExpressionsService implements PersistableState<ExpressionAstExpress
    */
   public readonly getTypes = (): ReturnType<Executor['getTypes']> => this.executor.getTypes();
 
-  public readonly execute: ExpressionsServiceStart['execute'] = ((ast, input, context, options) => {
-    const execution = this.executor.createExecution(ast, context, options);
+  public readonly execute: ExpressionsServiceStart['execute'] = ((ast, input, params) => {
+    const execution = this.executor.createExecution(ast, params);
     execution.start(input);
     return execution.contract;
   }) as ExpressionsServiceStart['execute'];
diff --git a/src/plugins/expressions/public/loader.ts b/src/plugins/expressions/public/loader.ts
index aef4b73f86e34..91c482621de36 100644
--- a/src/plugins/expressions/public/loader.ts
+++ b/src/plugins/expressions/public/loader.ts
@@ -145,18 +145,13 @@ export class ExpressionLoader {
       this.execution.cancel();
     }
     this.setParams(params);
-    this.execution = getExpressionsService().execute(
-      expression,
-      params.context,
-      {
-        search: params.searchContext,
-        variables: params.variables || {},
-        inspectorAdapters: params.inspectorAdapters,
-      },
-      {
-        debug: params.debug,
-      }
-    );
+    this.execution = getExpressionsService().execute(expression, params.context, {
+      searchContext: params.searchContext,
+      variables: params.variables || {},
+      inspectorAdapters: params.inspectorAdapters,
+      searchSessionId: params.searchSessionId,
+      debug: params.debug,
+    });
 
     const prevDataHandler = this.execution;
     const data = await prevDataHandler.getData();
@@ -188,6 +183,9 @@ export class ExpressionLoader {
     if (params.variables && this.params) {
       this.params.variables = params.variables;
     }
+    if (params.searchSessionId && this.params) {
+      this.params.searchSessionId = params.searchSessionId;
+    }
     this.params.debug = Boolean(params.debug);
 
     this.params.inspectorAdapters = (params.inspectorAdapters ||
diff --git a/src/plugins/expressions/public/public.api.md b/src/plugins/expressions/public/public.api.md
index 4739b9434bdaa..fe95cf5eb0cda 100644
--- a/src/plugins/expressions/public/public.api.md
+++ b/src/plugins/expressions/public/public.api.md
@@ -90,33 +90,32 @@ export type DatatableColumnType = '_source' | 'attachment' | 'boolean' | 'date'
 export type DatatableRow = Record<string, any>;
 
 // Warning: (ae-forgotten-export) The symbol "Adapters" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "ExpressionExecutionParams" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "DefaultInspectorAdapters" needs to be exported by the entry point index.d.ts
 // Warning: (ae-missing-release-tag) "Execution" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
 //
 // @public (undocumented)
-export class Execution<ExtraContext extends Record<string, unknown> = Record<string, unknown>, Input = unknown, Output = unknown, InspectorAdapters extends Adapters = ExtraContext['inspectorAdapters'] extends object ? ExtraContext['inspectorAdapters'] : DefaultInspectorAdapters> {
-    constructor(params: ExecutionParams<ExtraContext>);
+export class Execution<Input = unknown, Output = unknown, InspectorAdapters extends Adapters = ExpressionExecutionParams['inspectorAdapters'] extends object ? ExpressionExecutionParams['inspectorAdapters'] : DefaultInspectorAdapters> {
+    constructor(execution: ExecutionParams);
     cancel(): void;
     // (undocumented)
     cast(value: any, toTypeNames?: string[]): any;
-    readonly context: ExecutionContext<Input, InspectorAdapters> & ExtraContext;
-    readonly contract: ExecutionContract<ExtraContext, Input, Output, InspectorAdapters>;
+    readonly context: ExecutionContext<InspectorAdapters>;
+    readonly contract: ExecutionContract<Input, Output, InspectorAdapters>;
+    // (undocumented)
+    readonly execution: ExecutionParams;
     // (undocumented)
     readonly expression: string;
     input: Input;
     // (undocumented)
     get inspectorAdapters(): InspectorAdapters;
-    // Warning: (ae-forgotten-export) The symbol "ExpressionExecOptions" needs to be exported by the entry point index.d.ts
-    //
     // (undocumented)
-    interpret<T>(ast: ExpressionAstNode, input: T, options?: ExpressionExecOptions): Promise<unknown>;
+    interpret<T>(ast: ExpressionAstNode, input: T): Promise<unknown>;
     // (undocumented)
     invokeChain(chainArr: ExpressionAstFunction[], input: unknown): Promise<any>;
     // (undocumented)
     invokeFunction(fn: ExpressionFunction, input: unknown, args: Record<string, unknown>): Promise<any>;
     // (undocumented)
-    readonly params: ExecutionParams<ExtraContext>;
-    // (undocumented)
     resolveArgs(fnDef: ExpressionFunction, input: unknown, argAsts: any): Promise<any>;
     // (undocumented)
     get result(): Promise<Output | ExpressionValueError>;
@@ -134,15 +133,15 @@ export type ExecutionContainer<Output = ExpressionValue> = StateContainer<Execut
 // Warning: (ae-missing-release-tag) "ExecutionContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
 //
 // @public
-export interface ExecutionContext<Input = unknown, InspectorAdapters extends Adapters = Adapters> {
+export interface ExecutionContext<InspectorAdapters extends Adapters = Adapters> {
     abortSignal: AbortSignal;
-    getInitialInput: () => Input;
     // Warning: (ae-forgotten-export) The symbol "SavedObjectAttributes" needs to be exported by the entry point index.d.ts
     // Warning: (ae-forgotten-export) The symbol "SavedObject" needs to be exported by the entry point index.d.ts
     getSavedObject?: <T extends SavedObjectAttributes = SavedObjectAttributes>(type: string, id: string) => Promise<SavedObject<T>>;
-    inspectorAdapters: InspectorAdapters;
     // Warning: (ae-forgotten-export) The symbol "ExecutionContextSearch" needs to be exported by the entry point index.d.ts
-    search?: ExecutionContextSearch;
+    getSearchContext: () => ExecutionContextSearch;
+    getSearchSessionId: () => string | undefined;
+    inspectorAdapters: InspectorAdapters;
     types: Record<string, ExpressionType>;
     variables: Record<string, unknown>;
 }
@@ -150,11 +149,11 @@ export interface ExecutionContext<Input = unknown, InspectorAdapters extends Ada
 // Warning: (ae-missing-release-tag) "ExecutionContract" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
 //
 // @public
-export class ExecutionContract<ExtraContext extends Record<string, unknown> = Record<string, unknown>, Input = unknown, Output = unknown, InspectorAdapters = unknown> {
-    constructor(execution: Execution<ExtraContext, Input, Output, InspectorAdapters>);
+export class ExecutionContract<Input = unknown, Output = unknown, InspectorAdapters = unknown> {
+    constructor(execution: Execution<Input, Output, InspectorAdapters>);
     cancel: () => void;
     // (undocumented)
-    protected readonly execution: Execution<ExtraContext, Input, Output, InspectorAdapters>;
+    protected readonly execution: Execution<Input, Output, InspectorAdapters>;
     getAst: () => ExpressionAstExpression;
     getData: () => Promise<Output | ExpressionValueError>;
     getExpression: () => string;
@@ -166,16 +165,15 @@ export class ExecutionContract<ExtraContext extends Record<string, unknown> = Re
 // Warning: (ae-missing-release-tag) "ExecutionParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
 //
 // @public (undocumented)
-export interface ExecutionParams<ExtraContext extends Record<string, unknown> = Record<string, unknown>> {
+export interface ExecutionParams {
     // (undocumented)
     ast?: ExpressionAstExpression;
     // (undocumented)
-    context?: ExtraContext;
-    debug?: boolean;
-    // (undocumented)
     executor: Executor<any>;
     // (undocumented)
     expression?: string;
+    // (undocumented)
+    params: ExpressionExecutionParams;
 }
 
 // Warning: (ae-missing-release-tag) "ExecutionState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@@ -198,7 +196,7 @@ export class Executor<Context extends Record<string, unknown> = Record<string, u
     // (undocumented)
     get context(): Record<string, unknown>;
     // (undocumented)
-    createExecution<ExtraContext extends Record<string, unknown> = Record<string, unknown>, Input = unknown, Output = unknown>(ast: string | ExpressionAstExpression, context?: ExtraContext, { debug }?: ExpressionExecOptions): Execution<Context & ExtraContext, Input, Output>;
+    createExecution<Input = unknown, Output = unknown>(ast: string | ExpressionAstExpression, params?: ExpressionExecutionParams): Execution<Input, Output>;
     // (undocumented)
     static createWithDefaults<Ctx extends Record<string, unknown> = Record<string, unknown>>(state?: ExecutorState<Ctx>): Executor<Ctx>;
     // (undocumented)
@@ -228,7 +226,7 @@ export class Executor<Context extends Record<string, unknown> = Record<string, u
     registerFunction(functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)): void;
     // (undocumented)
     registerType(typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)): void;
-    run<Input, Output, ExtraContext extends Record<string, unknown> = Record<string, unknown>>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext, options?: ExpressionExecOptions): Promise<Output>;
+    run<Input, Output>(ast: string | ExpressionAstExpression, input: Input, params?: ExpressionExecutionParams): Promise<Output>;
     // (undocumented)
     readonly state: ExecutorContainer<Context>;
     // (undocumented)
@@ -613,12 +611,12 @@ export type ExpressionsServiceSetup = Pick<ExpressionsService, 'getFunction' | '
 //
 // @public
 export interface ExpressionsServiceStart {
-    execute: <Input = unknown, Output = unknown, ExtraContext extends Record<string, unknown> = Record<string, unknown>>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext, options?: ExpressionExecOptions) => ExecutionContract<ExtraContext, Input, Output>;
+    execute: <Input = unknown, Output = unknown>(ast: string | ExpressionAstExpression, input: Input, params?: ExpressionExecutionParams) => ExecutionContract<Input, Output>;
     fork: () => ExpressionsService;
     getFunction: (name: string) => ReturnType<Executor['getFunction']>;
     getRenderer: (name: string) => ReturnType<ExpressionRendererRegistry['get']>;
     getType: (name: string) => ReturnType<Executor['getType']>;
-    run: <Input, Output, ExtraContext extends Record<string, unknown> = Record<string, unknown>>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext, options?: ExpressionExecOptions) => Promise<Output>;
+    run: <Input, Output>(ast: string | ExpressionAstExpression, input: Input, params?: ExpressionExecutionParams) => Promise<Output>;
 }
 
 // Warning: (ae-missing-release-tag) "ExpressionsSetup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@@ -894,6 +892,8 @@ export interface IExpressionLoaderParams {
     // (undocumented)
     searchContext?: ExecutionContextSearch;
     // (undocumented)
+    searchSessionId?: string;
+    // (undocumented)
     uiState?: unknown;
     // (undocumented)
     variables?: Record<string, any>;
diff --git a/src/plugins/expressions/public/types/index.ts b/src/plugins/expressions/public/types/index.ts
index 054c5ac3dc467..1643b5734ef1a 100644
--- a/src/plugins/expressions/public/types/index.ts
+++ b/src/plugins/expressions/public/types/index.ts
@@ -53,6 +53,7 @@ export interface IExpressionLoaderParams {
   uiState?: unknown;
   inspectorAdapters?: Adapters;
   onRenderError?: RenderErrorHandlerFnType;
+  searchSessionId?: string;
 }
 
 export interface ExpressionRenderError extends Error {
diff --git a/src/plugins/expressions/server/server.api.md b/src/plugins/expressions/server/server.api.md
index fcdfd5ef3246c..d6925a027358c 100644
--- a/src/plugins/expressions/server/server.api.md
+++ b/src/plugins/expressions/server/server.api.md
@@ -87,34 +87,33 @@ export type DatatableColumnType = '_source' | 'attachment' | 'boolean' | 'date'
 export type DatatableRow = Record<string, any>;
 
 // Warning: (ae-forgotten-export) The symbol "Adapters" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "ExpressionExecutionParams" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "DefaultInspectorAdapters" needs to be exported by the entry point index.d.ts
 // Warning: (ae-missing-release-tag) "Execution" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
 //
 // @public (undocumented)
-export class Execution<ExtraContext extends Record<string, unknown> = Record<string, unknown>, Input = unknown, Output = unknown, InspectorAdapters extends Adapters = ExtraContext['inspectorAdapters'] extends object ? ExtraContext['inspectorAdapters'] : DefaultInspectorAdapters> {
-    constructor(params: ExecutionParams<ExtraContext>);
+export class Execution<Input = unknown, Output = unknown, InspectorAdapters extends Adapters = ExpressionExecutionParams['inspectorAdapters'] extends object ? ExpressionExecutionParams['inspectorAdapters'] : DefaultInspectorAdapters> {
+    constructor(execution: ExecutionParams);
     cancel(): void;
     // (undocumented)
     cast(value: any, toTypeNames?: string[]): any;
-    readonly context: ExecutionContext<Input, InspectorAdapters> & ExtraContext;
+    readonly context: ExecutionContext<InspectorAdapters>;
     // Warning: (ae-forgotten-export) The symbol "ExecutionContract" needs to be exported by the entry point index.d.ts
-    readonly contract: ExecutionContract<ExtraContext, Input, Output, InspectorAdapters>;
+    readonly contract: ExecutionContract<Input, Output, InspectorAdapters>;
+    // (undocumented)
+    readonly execution: ExecutionParams;
     // (undocumented)
     readonly expression: string;
     input: Input;
     // (undocumented)
     get inspectorAdapters(): InspectorAdapters;
-    // Warning: (ae-forgotten-export) The symbol "ExpressionExecOptions" needs to be exported by the entry point index.d.ts
-    //
     // (undocumented)
-    interpret<T>(ast: ExpressionAstNode, input: T, options?: ExpressionExecOptions): Promise<unknown>;
+    interpret<T>(ast: ExpressionAstNode, input: T): Promise<unknown>;
     // (undocumented)
     invokeChain(chainArr: ExpressionAstFunction[], input: unknown): Promise<any>;
     // (undocumented)
     invokeFunction(fn: ExpressionFunction, input: unknown, args: Record<string, unknown>): Promise<any>;
     // (undocumented)
-    readonly params: ExecutionParams<ExtraContext>;
-    // (undocumented)
     resolveArgs(fnDef: ExpressionFunction, input: unknown, argAsts: any): Promise<any>;
     // (undocumented)
     get result(): Promise<Output | ExpressionValueError>;
@@ -132,15 +131,15 @@ export type ExecutionContainer<Output = ExpressionValue> = StateContainer<Execut
 // Warning: (ae-missing-release-tag) "ExecutionContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
 //
 // @public
-export interface ExecutionContext<Input = unknown, InspectorAdapters extends Adapters = Adapters> {
+export interface ExecutionContext<InspectorAdapters extends Adapters = Adapters> {
     abortSignal: AbortSignal;
-    getInitialInput: () => Input;
     // Warning: (ae-forgotten-export) The symbol "SavedObjectAttributes" needs to be exported by the entry point index.d.ts
     // Warning: (ae-forgotten-export) The symbol "SavedObject" needs to be exported by the entry point index.d.ts
     getSavedObject?: <T extends SavedObjectAttributes = SavedObjectAttributes>(type: string, id: string) => Promise<SavedObject<T>>;
-    inspectorAdapters: InspectorAdapters;
     // Warning: (ae-forgotten-export) The symbol "ExecutionContextSearch" needs to be exported by the entry point index.d.ts
-    search?: ExecutionContextSearch;
+    getSearchContext: () => ExecutionContextSearch;
+    getSearchSessionId: () => string | undefined;
+    inspectorAdapters: InspectorAdapters;
     types: Record<string, ExpressionType>;
     variables: Record<string, unknown>;
 }
@@ -148,16 +147,15 @@ export interface ExecutionContext<Input = unknown, InspectorAdapters extends Ada
 // Warning: (ae-missing-release-tag) "ExecutionParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
 //
 // @public (undocumented)
-export interface ExecutionParams<ExtraContext extends Record<string, unknown> = Record<string, unknown>> {
+export interface ExecutionParams {
     // (undocumented)
     ast?: ExpressionAstExpression;
     // (undocumented)
-    context?: ExtraContext;
-    debug?: boolean;
-    // (undocumented)
     executor: Executor<any>;
     // (undocumented)
     expression?: string;
+    // (undocumented)
+    params: ExpressionExecutionParams;
 }
 
 // Warning: (ae-missing-release-tag) "ExecutionState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@@ -180,7 +178,7 @@ export class Executor<Context extends Record<string, unknown> = Record<string, u
     // (undocumented)
     get context(): Record<string, unknown>;
     // (undocumented)
-    createExecution<ExtraContext extends Record<string, unknown> = Record<string, unknown>, Input = unknown, Output = unknown>(ast: string | ExpressionAstExpression, context?: ExtraContext, { debug }?: ExpressionExecOptions): Execution<Context & ExtraContext, Input, Output>;
+    createExecution<Input = unknown, Output = unknown>(ast: string | ExpressionAstExpression, params?: ExpressionExecutionParams): Execution<Input, Output>;
     // (undocumented)
     static createWithDefaults<Ctx extends Record<string, unknown> = Record<string, unknown>>(state?: ExecutorState<Ctx>): Executor<Ctx>;
     // (undocumented)
@@ -210,7 +208,7 @@ export class Executor<Context extends Record<string, unknown> = Record<string, u
     registerFunction(functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)): void;
     // (undocumented)
     registerType(typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)): void;
-    run<Input, Output, ExtraContext extends Record<string, unknown> = Record<string, unknown>>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext, options?: ExpressionExecOptions): Promise<Output>;
+    run<Input, Output>(ast: string | ExpressionAstExpression, input: Input, params?: ExpressionExecutionParams): Promise<Output>;
     // (undocumented)
     readonly state: ExecutorContainer<Context>;
     // (undocumented)
diff --git a/src/plugins/home/public/application/components/solutions_section/solutions_section.tsx b/src/plugins/home/public/application/components/solutions_section/solutions_section.tsx
index 13b70383147eb..bbc7f28235d6a 100644
--- a/src/plugins/home/public/application/components/solutions_section/solutions_section.tsx
+++ b/src/plugins/home/public/application/components/solutions_section/solutions_section.tsx
@@ -25,8 +25,8 @@ import { SolutionPanel } from './solution_panel';
 import { FeatureCatalogueEntry, FeatureCatalogueSolution } from '../../../';
 
 const sortByOrder = (
-  { order: orderA = 0 }: FeatureCatalogueSolution,
-  { order: orderB = 0 }: FeatureCatalogueSolution
+  { order: orderA = 0 }: FeatureCatalogueSolution | FeatureCatalogueEntry,
+  { order: orderB = 0 }: FeatureCatalogueSolution | FeatureCatalogueEntry
 ) => orderA - orderB;
 
 interface Props {
@@ -38,7 +38,9 @@ interface Props {
 export const SolutionsSection: FC<Props> = ({ addBasePath, solutions, directories }) => {
   // Separate Kibana from other solutions
   const kibana = solutions.find(({ id }) => id === 'kibana');
-  const kibanaApps = directories.filter(({ solutionId }) => solutionId === 'kibana');
+  const kibanaApps = directories
+    .filter(({ solutionId }) => solutionId === 'kibana')
+    .sort(sortByOrder);
   solutions = solutions.sort(sortByOrder).filter(({ id }) => id !== 'kibana');
 
   return (
diff --git a/src/plugins/kibana_overview/public/plugin.ts b/src/plugins/kibana_overview/public/plugin.ts
index 663058ad16ec8..1139002dc19b6 100644
--- a/src/plugins/kibana_overview/public/plugin.ts
+++ b/src/plugins/kibana_overview/public/plugin.ts
@@ -109,7 +109,7 @@ export class KibanaOverviewPlugin
             defaultMessage: 'Search and find insights.',
           }),
           i18n.translate('kibanaOverview.kibana.appDescription3', {
-            defaultMessage: 'Design pixel-perfect reports.',
+            defaultMessage: 'Design pixel-perfect presentations.',
           }),
           i18n.translate('kibanaOverview.kibana.appDescription4', {
             defaultMessage: 'Plot geographic data.',
diff --git a/src/plugins/kibana_usage_collection/server/collectors/csp/csp_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/csp/csp_collector.ts
index c45a83588ee44..8cd60e5477d02 100644
--- a/src/plugins/kibana_usage_collection/server/collectors/csp/csp_collector.ts
+++ b/src/plugins/kibana_usage_collection/server/collectors/csp/csp_collector.ts
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import { UsageCollectionSetup, CollectorOptions } from 'src/plugins/usage_collection/server';
+import { UsageCollectionSetup, UsageCollectorOptions } from 'src/plugins/usage_collection/server';
 import { HttpServiceSetup, CspConfig } from '../../../../../core/server';
 
 interface Usage {
@@ -26,7 +26,7 @@ interface Usage {
   rulesChangedFromDefault: boolean;
 }
 
-export function createCspCollector(http: HttpServiceSetup): CollectorOptions<Usage> {
+export function createCspCollector(http: HttpServiceSetup): UsageCollectorOptions<Usage> {
   return {
     type: 'csp',
     isReady: () => true,
diff --git a/src/plugins/telemetry/schema/legacy_plugins.json b/src/plugins/telemetry/schema/legacy_plugins.json
new file mode 100644
index 0000000000000..1a7c0ccb15082
--- /dev/null
+++ b/src/plugins/telemetry/schema/legacy_plugins.json
@@ -0,0 +1,21 @@
+{
+  "properties": {
+    "localization": {
+      "properties": {
+        "locale": {
+          "type": "keyword"
+        },
+        "integrities": {
+          "properties": {
+            "DYNAMIC_KEY": {
+              "type": "text"
+            }
+          }
+        },
+        "labelsCount": {
+          "type": "long"
+        }
+      }
+    }
+  }
+}
diff --git a/src/plugins/usage_collection/server/collector/collector.test.ts b/src/plugins/usage_collection/server/collector/collector.test.ts
index 375fe4f7686c0..875414fbeec48 100644
--- a/src/plugins/usage_collection/server/collector/collector.test.ts
+++ b/src/plugins/usage_collection/server/collector/collector.test.ts
@@ -122,6 +122,7 @@ describe('collector', () => {
         type: 'my_test_collector',
         isReady: () => false,
         fetch: () => fetchOutput,
+        schema: { testPass: { type: 'long' } },
       });
       expect(collector.formatForBulkUpload(fetchOutput)).toStrictEqual({
         type: 'kibana_stats',
diff --git a/src/plugins/usage_collection/server/collector/collector.ts b/src/plugins/usage_collection/server/collector/collector.ts
index 11a709c037783..951418d448cbd 100644
--- a/src/plugins/usage_collection/server/collector/collector.ts
+++ b/src/plugins/usage_collection/server/collector/collector.ts
@@ -71,17 +71,27 @@ export interface CollectorFetchContext {
 }
 
 export interface CollectorOptions<T = unknown, U = T> {
+  /**
+   * Unique string identifier for the collector
+   */
   type: string;
   init?: Function;
+  /**
+   * Method to return `true`/`false` to confirm if the collector is ready for the `fetch` method to be called.
+   */
+  isReady: () => Promise<boolean> | boolean;
+  /**
+   * Schema definition of the output of the `fetch` method.
+   */
   schema?: MakeSchemaFrom<T>;
   fetch: (collectorFetchContext: CollectorFetchContext) => Promise<T> | T;
   /*
    * A hook for allowing the fetched data payload to be organized into a typed
    * data model for internal bulk upload. See defaultFormatterForBulkUpload for
    * a generic example.
+   * @deprecated Used only by the Legacy Monitoring collection (to be removed in 8.0)
    */
   formatForBulkUpload?: CollectorFormatForBulkUpload<T, U>;
-  isReady: () => Promise<boolean> | boolean;
 }
 
 export class Collector<T = unknown, U = T> {
diff --git a/src/plugins/usage_collection/server/collector/collector_set.test.ts b/src/plugins/usage_collection/server/collector/collector_set.test.ts
index 45a3437777c5f..359a2d214f991 100644
--- a/src/plugins/usage_collection/server/collector/collector_set.test.ts
+++ b/src/plugins/usage_collection/server/collector/collector_set.test.ts
@@ -20,7 +20,7 @@
 import { noop } from 'lodash';
 import { Collector } from './collector';
 import { CollectorSet } from './collector_set';
-import { UsageCollector } from './usage_collector';
+import { UsageCollector, UsageCollectorOptions } from './usage_collector';
 import {
   elasticsearchServiceMock,
   loggingSystemMock,
@@ -73,8 +73,9 @@ describe('CollectorSet', () => {
           // Even for Collector vs. UsageCollector
           new UsageCollector(logger, {
             type: 'test_duplicated',
-            fetch: () => 2,
+            fetch: () => ({ prop: 2 }),
             isReady: () => false,
+            schema: { prop: { type: 'long' } },
           })
         )
       ).toThrowError(`Usage collector's type "test_duplicated" is duplicated.`);
@@ -252,7 +253,12 @@ describe('CollectorSet', () => {
   });
 
   describe('isUsageCollector', () => {
-    const collectorOptions = { type: 'MY_TEST_COLLECTOR', fetch: () => {}, isReady: () => true };
+    const collectorOptions: UsageCollectorOptions = {
+      type: 'MY_TEST_COLLECTOR',
+      fetch: () => ({ test: 1 }),
+      isReady: () => true,
+      schema: { test: { type: 'long' } },
+    };
 
     it('returns true only for UsageCollector instances', () => {
       const collectors = new CollectorSet({ logger });
diff --git a/src/plugins/usage_collection/server/collector/collector_set.ts b/src/plugins/usage_collection/server/collector/collector_set.ts
index 4e64cbc1bf30f..c52830cda6513 100644
--- a/src/plugins/usage_collection/server/collector/collector_set.ts
+++ b/src/plugins/usage_collection/server/collector/collector_set.ts
@@ -26,7 +26,7 @@ import {
   SavedObjectsClientContract,
 } from 'kibana/server';
 import { Collector, CollectorOptions } from './collector';
-import { UsageCollector } from './usage_collector';
+import { UsageCollector, UsageCollectorOptions } from './usage_collector';
 
 interface CollectorSetConfig {
   logger: Logger;
@@ -45,10 +45,22 @@ export class CollectorSet {
     this.maximumWaitTimeForAllCollectorsInS = maximumWaitTimeForAllCollectorsInS || 60;
   }
 
-  public makeStatsCollector = <T, U>(options: CollectorOptions<T, U>) => {
+  public makeStatsCollector = <
+    T,
+    U,
+    O extends CollectorOptions<T, U> = CollectorOptions<T, U> // Used to allow extra properties (the Collector constructor extends the class with the additional options provided)
+  >(
+    options: O
+  ) => {
     return new Collector(this.logger, options);
   };
-  public makeUsageCollector = <T, U = T>(options: CollectorOptions<T, U>) => {
+  public makeUsageCollector = <
+    T,
+    U = T,
+    O extends UsageCollectorOptions<T, U> = UsageCollectorOptions<T, U>
+  >(
+    options: O
+  ) => {
     return new UsageCollector(this.logger, options);
   };
 
diff --git a/src/plugins/usage_collection/server/collector/index.ts b/src/plugins/usage_collection/server/collector/index.ts
index c294ba77d3cdb..da85f9ab181c9 100644
--- a/src/plugins/usage_collection/server/collector/index.ts
+++ b/src/plugins/usage_collection/server/collector/index.ts
@@ -26,4 +26,4 @@ export {
   CollectorOptions,
   CollectorFetchContext,
 } from './collector';
-export { UsageCollector } from './usage_collector';
+export { UsageCollector, UsageCollectorOptions } from './usage_collector';
diff --git a/src/plugins/usage_collection/server/collector/usage_collector.ts b/src/plugins/usage_collection/server/collector/usage_collector.ts
index bf861a94fccff..5bfc36537e0b0 100644
--- a/src/plugins/usage_collection/server/collector/usage_collector.ts
+++ b/src/plugins/usage_collection/server/collector/usage_collector.ts
@@ -17,13 +17,22 @@
  * under the License.
  */
 
+import { Logger } from 'src/core/server';
 import { KIBANA_STATS_TYPE } from '../../common/constants';
-import { Collector } from './collector';
+import { Collector, CollectorOptions } from './collector';
+
+// Enforce the `schema` property for UsageCollectors
+export type UsageCollectorOptions<T = unknown, U = T> = CollectorOptions<T, U> &
+  Required<Pick<CollectorOptions<T, U>, 'schema'>>;
 
 export class UsageCollector<T = unknown, U = { usage: { [key: string]: T } }> extends Collector<
   T,
   U
 > {
+  constructor(protected readonly log: Logger, collectorOptions: UsageCollectorOptions<T, U>) {
+    super(log, collectorOptions);
+  }
+
   protected defaultFormatterForBulkUpload(result: T) {
     return {
       type: KIBANA_STATS_TYPE,
diff --git a/src/plugins/usage_collection/server/index.ts b/src/plugins/usage_collection/server/index.ts
index 80e34b1502cda..f7a08fdb5e9dd 100644
--- a/src/plugins/usage_collection/server/index.ts
+++ b/src/plugins/usage_collection/server/index.ts
@@ -25,6 +25,7 @@ export {
   MakeSchemaFrom,
   SchemaField,
   CollectorOptions,
+  UsageCollectorOptions,
   Collector,
   CollectorFetchContext,
 } from './collector';
diff --git a/src/plugins/vis_default_editor/public/components/agg_params_helper.test.ts b/src/plugins/vis_default_editor/public/components/agg_params_helper.test.ts
index 834ad8b70ad0d..a56155db02f6b 100644
--- a/src/plugins/vis_default_editor/public/components/agg_params_helper.test.ts
+++ b/src/plugins/vis_default_editor/public/components/agg_params_helper.test.ts
@@ -33,6 +33,7 @@ import { FieldParamEditor, OrderByParamEditor } from './controls';
 import { EditorConfig } from './utils';
 import { Schema } from '../schemas';
 import { EditorVisState } from './sidebar/state/reducers';
+import { groupAndSortBy } from '../utils';
 
 jest.mock('../utils', () => ({
   groupAndSortBy: jest.fn(() => ['indexedFields']),
@@ -169,6 +170,9 @@ describe('DefaultEditorAggParams helpers', () => {
         ],
         advanced: [],
       });
+
+      // Should be grouped using displayName as label
+      expect(groupAndSortBy).toHaveBeenCalledWith(expect.anything(), 'type', 'displayName', 'name');
     });
   });
 
diff --git a/src/plugins/vis_default_editor/public/components/agg_params_helper.ts b/src/plugins/vis_default_editor/public/components/agg_params_helper.ts
index b13ca32601aa9..271fc75a0853e 100644
--- a/src/plugins/vis_default_editor/public/components/agg_params_helper.ts
+++ b/src/plugins/vis_default_editor/public/components/agg_params_helper.ts
@@ -93,7 +93,7 @@ function getAggParamsToRender({
         }
       }
       fields = filterAggTypeFields(availableFields, agg);
-      indexedFields = groupAndSortBy(fields, 'type', 'name');
+      indexedFields = groupAndSortBy(fields, 'type', 'displayName', 'name');
 
       if (fields && !indexedFields.length && index > 0) {
         // don't draw the rest of the options if there are no indexed fields and it's an extra param (index > 0).
diff --git a/src/plugins/vis_default_editor/public/components/controls/field.tsx b/src/plugins/vis_default_editor/public/components/controls/field.tsx
index bfc4f881f8458..41d6db25da5e2 100644
--- a/src/plugins/vis_default_editor/public/components/controls/field.tsx
+++ b/src/plugins/vis_default_editor/public/components/controls/field.tsx
@@ -52,7 +52,7 @@ function FieldParamEditor({
 }: FieldParamEditorProps) {
   const [isDirty, setIsDirty] = useState(false);
   const selectedOptions: ComboBoxGroupedOptions<IndexPatternField> = value
-    ? [{ label: value.displayName || value.name, target: value }]
+    ? [{ label: value.displayName, target: value, key: value.name }]
     : [];
 
   const onChange = (options: EuiComboBoxOptionOption[]) => {
diff --git a/src/plugins/vis_default_editor/public/utils.ts b/src/plugins/vis_default_editor/public/utils.ts
index d0a9c067e9da2..11b7c07acc2c2 100644
--- a/src/plugins/vis_default_editor/public/utils.ts
+++ b/src/plugins/vis_default_editor/public/utils.ts
@@ -18,10 +18,12 @@
  */
 
 interface ComboBoxOption<T> {
+  key?: string;
   label: string;
   target: T;
 }
 interface ComboBoxGroupedOption<T> {
+  key?: string;
   label: string;
   options: Array<ComboBoxOption<T>>;
 }
@@ -40,15 +42,22 @@ export type ComboBoxGroupedOptions<T> = Array<GroupOrOption<T>>;
  * @returns An array of grouped and sorted alphabetically `objects` that are compatible with EuiComboBox options.
  */
 export function groupAndSortBy<
-  T extends Record<TGroupBy | TLabelName, string>,
+  T extends Record<TGroupBy | TLabelName | TKeyName, string>,
   TGroupBy extends string = 'type',
-  TLabelName extends string = 'title'
->(objects: T[], groupBy: TGroupBy, labelName: TLabelName): ComboBoxGroupedOptions<T> {
+  TLabelName extends string = 'title',
+  TKeyName extends string = never
+>(
+  objects: T[],
+  groupBy: TGroupBy,
+  labelName: TLabelName,
+  keyName?: TKeyName
+): ComboBoxGroupedOptions<T> {
   const groupedOptions = objects.reduce((array, obj) => {
     const group = array.find((element) => element.label === obj[groupBy]);
     const option = {
       label: obj[labelName],
       target: obj,
+      ...(keyName ? { key: obj[keyName] } : {}),
     };
 
     if (group && group.options) {
diff --git a/src/plugins/vis_type_timeseries/server/lib/get_fields.ts b/src/plugins/vis_type_timeseries/server/lib/get_fields.ts
index 682d0a071e50d..b52188129f77f 100644
--- a/src/plugins/vis_type_timeseries/server/lib/get_fields.ts
+++ b/src/plugins/vis_type_timeseries/server/lib/get_fields.ts
@@ -45,7 +45,7 @@ export async function getFields(
     payload: {},
     pre: {
       indexPatternsService: new IndexPatternsFetcher(
-        requestContext.core.elasticsearch.legacy.client.callAsCurrentUser
+        requestContext.core.elasticsearch.client.asCurrentUser
       ),
     },
     getUiSettingsService: () => requestContext.core.uiSettings.client,
diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.js b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.js
index ceae784cf74a6..613f33a47f1f4 100644
--- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.js
+++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.js
@@ -50,7 +50,7 @@ describe('AbstractSearchStrategy', () => {
     expect(fields).toBe(mockedFields);
     expect(req.pre.indexPatternsService.getFieldsForWildcard).toHaveBeenCalledWith({
       pattern: indexPattern,
-      fieldCapsOptions: { allowNoIndices: true },
+      fieldCapsOptions: { allow_no_indices: true },
     });
   });
 
diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts
index 7b62ad310a354..8b16048f0dce0 100644
--- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts
+++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts
@@ -86,7 +86,7 @@ export class AbstractSearchStrategy {
 
     return await indexPatternsService!.getFieldsForWildcard({
       pattern: indexPattern,
-      fieldCapsOptions: { allowNoIndices: true },
+      fieldCapsOptions: { allow_no_indices: true },
     });
   }
 
diff --git a/src/plugins/vis_type_vega/public/vega_fn.ts b/src/plugins/vis_type_vega/public/vega_fn.ts
index c109bb3c6e90c..c88b78948133c 100644
--- a/src/plugins/vis_type_vega/public/vega_fn.ts
+++ b/src/plugins/vis_type_vega/public/vega_fn.ts
@@ -53,7 +53,7 @@ export const createVegaFn = (
   Input,
   Arguments,
   Output,
-  ExecutionContext<unknown, VegaInspectorAdapters>
+  ExecutionContext<VegaInspectorAdapters>
 > => ({
   name: 'vega',
   type: 'render',
diff --git a/test/functional/apps/discover/_discover_histogram.ts b/test/functional/apps/discover/_discover_histogram.ts
index e06783174e83b..672becca614c9 100644
--- a/test/functional/apps/discover/_discover_histogram.ts
+++ b/test/functional/apps/discover/_discover_histogram.ts
@@ -31,7 +31,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
     'dateFormat:tz': 'Europe/Berlin',
   };
 
-  describe('discover histogram', function describeIndexTests() {
+  // FLAKY: https://github.com/elastic/kibana/issues/81576
+  describe.skip('discover histogram', function describeIndexTests() {
     before(async () => {
       await esArchiver.loadIfNeeded('logstash_functional');
       await esArchiver.load('long_window_logstash');
diff --git a/test/functional/apps/discover/_doc_navigation.js b/test/functional/apps/discover/_doc_navigation.js
index 87a150c7d6961..31aef96918ffa 100644
--- a/test/functional/apps/discover/_doc_navigation.js
+++ b/test/functional/apps/discover/_doc_navigation.js
@@ -28,7 +28,8 @@ export default function ({ getService, getPageObjects }) {
   const esArchiver = getService('esArchiver');
   const retry = getService('retry');
 
-  describe('doc link in discover', function contextSize() {
+  // FLAKY: https://github.com/elastic/kibana/issues/78373
+  describe.skip('doc link in discover', function contextSize() {
     beforeEach(async function () {
       log.debug('load kibana index with default index pattern');
       await esArchiver.loadIfNeeded('discover');
diff --git a/test/functional/page_objects/common_page.ts b/test/functional/page_objects/common_page.ts
index cc229ef0c2e08..4a14d43aec249 100644
--- a/test/functional/page_objects/common_page.ts
+++ b/test/functional/page_objects/common_page.ts
@@ -117,11 +117,12 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
         } else {
           log.debug(`navigateToUrl ${appUrl}`);
           await browser.get(appUrl, insertTimestamp);
-          // accept alert if it pops up
-          const alert = await browser.getAlert();
-          await alert?.accept();
         }
 
+        // accept alert if it pops up
+        const alert = await browser.getAlert();
+        await alert?.accept();
+
         const currentUrl = shouldLoginIfPrompted
           ? await this.loginIfPrompted(appUrl, insertTimestamp)
           : await browser.getCurrentUrl();
diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/app/components/main.tsx b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/app/components/main.tsx
index b4f9634b23d29..8c62fa246dd59 100644
--- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/app/components/main.tsx
+++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/app/components/main.tsx
@@ -63,7 +63,7 @@ class Main extends React.Component<{}, State> {
       return getExpressions()
         .execute(expression, context || { type: 'null' }, {
           inspectorAdapters: adapters,
-          search: initialContext as any,
+          searchContext: initialContext as any,
         })
         .getData();
     };
diff --git a/x-pack/plugins/actions/server/saved_objects/migrations.test.ts b/x-pack/plugins/actions/server/saved_objects/migrations.test.ts
index 1fa5889e77cb0..947d84fcfc638 100644
--- a/x-pack/plugins/actions/server/saved_objects/migrations.test.ts
+++ b/x-pack/plugins/actions/server/saved_objects/migrations.test.ts
@@ -24,7 +24,11 @@ describe('7.10.0', () => {
   test('add hasAuth config property for .email actions', () => {
     const migration710 = getMigrations(encryptedSavedObjectsSetup)['7.10.0'];
     const action = getMockDataForEmail({});
-    expect(migration710(action, context)).toMatchObject({
+    const migratedAction = migration710(action, context);
+    expect(migratedAction.attributes.config).toEqual({
+      hasAuth: true,
+    });
+    expect(migratedAction).toEqual({
       ...action,
       attributes: {
         ...action.attributes,
@@ -38,7 +42,11 @@ describe('7.10.0', () => {
   test('rename cases configuration object', () => {
     const migration710 = getMigrations(encryptedSavedObjectsSetup)['7.10.0'];
     const action = getMockData({});
-    expect(migration710(action, context)).toMatchObject({
+    const migratedAction = migration710(action, context);
+    expect(migratedAction.attributes.config).toEqual({
+      incidentConfiguration: { mapping: [] },
+    });
+    expect(migratedAction).toEqual({
       ...action,
       attributes: {
         ...action.attributes,
diff --git a/x-pack/plugins/actions/server/saved_objects/migrations.ts b/x-pack/plugins/actions/server/saved_objects/migrations.ts
index 993beef8d9b2b..35d30accecedb 100644
--- a/x-pack/plugins/actions/server/saved_objects/migrations.ts
+++ b/x-pack/plugins/actions/server/saved_objects/migrations.ts
@@ -70,6 +70,9 @@ function renameCasesConfigurationObject(
 const addHasAuthConfigurationObject = (
   doc: SavedObjectUnsanitizedDoc<RawAction>
 ): SavedObjectUnsanitizedDoc<RawAction> => {
+  if (doc.attributes.actionTypeId !== '.email') {
+    return doc;
+  }
   const hasAuth = !!doc.attributes.secrets.user || !!doc.attributes.secrets.password;
   return {
     ...doc,
diff --git a/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts
index d9af3d0ae6d5b..8e345d6ff66a8 100644
--- a/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts
+++ b/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts
@@ -621,9 +621,7 @@ describe('Task Runner', () => {
     expect(await taskRunner.run()).toMatchInlineSnapshot(`
       Object {
         "runAt": 1970-01-01T00:00:10.000Z,
-        "state": Object {
-          "previousStartedAt": 1970-01-01T00:00:00.000Z,
-        },
+        "state": Object {},
       }
     `);
     expect(taskRunnerFactoryInitializerParams.logger.error).toHaveBeenCalledWith(
@@ -727,9 +725,7 @@ describe('Task Runner', () => {
     expect(runnerResult).toMatchInlineSnapshot(`
       Object {
         "runAt": 1970-01-01T00:00:10.000Z,
-        "state": Object {
-          "previousStartedAt": 1970-01-01T00:00:00.000Z,
-        },
+        "state": Object {},
       }
     `);
 
@@ -781,9 +777,7 @@ describe('Task Runner', () => {
     expect(runnerResult).toMatchInlineSnapshot(`
       Object {
         "runAt": 1970-01-01T00:05:00.000Z,
-        "state": Object {
-          "previousStartedAt": 1970-01-01T00:00:00.000Z,
-        },
+        "state": Object {},
       }
     `);
   });
@@ -814,9 +808,7 @@ describe('Task Runner', () => {
     expect(runnerResult).toMatchInlineSnapshot(`
       Object {
         "runAt": 1970-01-01T00:05:00.000Z,
-        "state": Object {
-          "previousStartedAt": 1970-01-01T00:00:00.000Z,
-        },
+        "state": Object {},
       }
     `);
   });
@@ -846,13 +838,48 @@ describe('Task Runner', () => {
     expect(runnerResult).toMatchInlineSnapshot(`
       Object {
         "runAt": 1970-01-01T00:05:00.000Z,
-        "state": Object {
-          "previousStartedAt": 1970-01-01T00:00:00.000Z,
-        },
+        "state": Object {},
       }
     `);
   });
 
+  test(`doesn't change previousStartedAt when it fails to run`, async () => {
+    const originalAlertSate = {
+      previousStartedAt: '1970-01-05T00:00:00.000Z',
+    };
+
+    alertType.executor.mockImplementation(
+      ({ services: executorServices }: AlertExecutorOptions) => {
+        throw new Error('OMG');
+      }
+    );
+
+    const taskRunner = new TaskRunner(
+      alertType,
+      {
+        ...mockedTaskInstance,
+        state: originalAlertSate,
+      },
+      taskRunnerFactoryInitializerParams
+    );
+
+    alertsClient.get.mockResolvedValueOnce(mockedAlertTypeSavedObject);
+    encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce({
+      id: '1',
+      type: 'alert',
+      attributes: {
+        apiKey: Buffer.from('123:abc').toString('base64'),
+      },
+      references: [],
+    });
+
+    const runnerResult = await taskRunner.run();
+
+    expect(runnerResult.state.previousStartedAt).toEqual(
+      new Date(originalAlertSate.previousStartedAt)
+    );
+  });
+
   test('avoids rescheduling a failed Alert Task Runner when it throws due to failing to fetch the alert', async () => {
     alertsClient.get.mockImplementation(() => {
       throw SavedObjectsErrorHelpers.createGenericNotFoundError('task', '1');
@@ -878,9 +905,7 @@ describe('Task Runner', () => {
     expect(runnerResult).toMatchInlineSnapshot(`
       Object {
         "runAt": undefined,
-        "state": Object {
-          "previousStartedAt": 1970-01-01T00:00:00.000Z,
-        },
+        "state": Object {},
       }
     `);
   });
diff --git a/x-pack/plugins/alerts/server/task_runner/task_runner.ts b/x-pack/plugins/alerts/server/task_runner/task_runner.ts
index 1ccf14a3a5334..7da16717aef9f 100644
--- a/x-pack/plugins/alerts/server/task_runner/task_runner.ts
+++ b/x-pack/plugins/alerts/server/task_runner/task_runner.ts
@@ -322,7 +322,7 @@ export class TaskRunner {
   async run(): Promise<AlertTaskRunResult> {
     const {
       params: { alertId, spaceId },
-      startedAt: previousStartedAt,
+      startedAt,
       state: originalState,
     } = this.taskInstance;
 
@@ -360,7 +360,7 @@ export class TaskRunner {
         (stateUpdates: AlertTaskState) => {
           return {
             ...stateUpdates,
-            previousStartedAt,
+            previousStartedAt: startedAt,
           };
         },
         (err: Error) => {
@@ -370,10 +370,7 @@ export class TaskRunner {
           } else {
             this.logger.error(message);
           }
-          return {
-            ...originalState,
-            previousStartedAt,
-          };
+          return originalState;
         }
       ),
       runAt: resolveErr<Date | undefined, Error>(runAt, (err) => {
diff --git a/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts b/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts
index 49030dc8cacc5..cf1f4852002ec 100644
--- a/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts
+++ b/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts
@@ -5,7 +5,6 @@
  */
 
 import LRU from 'lru-cache';
-import { LegacyAPICaller } from '../../../../../../src/core/server';
 import {
   IndexPatternsFetcher,
   FieldDescriptor,
@@ -45,8 +44,7 @@ export const getDynamicIndexPattern = async ({
   }
 
   const indexPatternsFetcher = new IndexPatternsFetcher(
-    (...rest: Parameters<LegacyAPICaller>) =>
-      context.core.elasticsearch.legacy.client.callAsCurrentUser(...rest)
+    context.core.elasticsearch.client.asCurrentUser
   );
 
   // Since `getDynamicIndexPattern` is called in setup_request (and thus by every endpoint)
diff --git a/x-pack/plugins/canvas/public/feature_catalogue_entry.ts b/x-pack/plugins/canvas/public/feature_catalogue_entry.ts
index ccc642177780d..2b6d2f105454b 100644
--- a/x-pack/plugins/canvas/public/feature_catalogue_entry.ts
+++ b/x-pack/plugins/canvas/public/feature_catalogue_entry.ts
@@ -11,7 +11,7 @@ export const featureCatalogueEntry = {
   id: 'canvas',
   title: 'Canvas',
   subtitle: i18n.translate('xpack.canvas.featureCatalogue.canvasSubtitle', {
-    defaultMessage: 'Design pixel-perfect reports.',
+    defaultMessage: 'Design pixel-perfect presentations.',
   }),
   description: i18n.translate('xpack.canvas.appDescription', {
     defaultMessage: 'Showcase your data in a pixel-perfect way.',
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts
index 374a2420f5ba7..decf1e2158744 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts
@@ -11,6 +11,16 @@ export enum ApiTokenTypes {
   Search = 'search',
 }
 
+export const CREATE_MESSAGE = i18n.translate('xpack.enterpriseSearch.appSearch.tokens.created', {
+  defaultMessage: 'Successfully created key.',
+});
+export const UPDATE_MESSAGE = i18n.translate('xpack.enterpriseSearch.appSearch.tokens.update', {
+  defaultMessage: 'Successfully updated API Key.',
+});
+export const DELETE_MESSAGE = i18n.translate('xpack.enterpriseSearch.appSearch.tokens.deleted', {
+  defaultMessage: 'Successfully deleted key.',
+});
+
 export const SEARCH_DISPLAY = i18n.translate(
   'xpack.enterpriseSearch.appSearch.tokens.permissions.display.search',
   {
@@ -81,3 +91,7 @@ export const TOKEN_TYPE_INFO = [
   { value: ApiTokenTypes.Private, text: TOKEN_TYPE_DISPLAY_NAMES[ApiTokenTypes.Private] },
   { value: ApiTokenTypes.Admin, text: TOKEN_TYPE_DISPLAY_NAMES[ApiTokenTypes.Admin] },
 ];
+
+export const FLYOUT_ARIA_LABEL_ID = 'credentialsFlyoutTitle';
+
+export const DOCS_HREF = 'https://www.elastic.co/guide/en/app-search/current/authentication.html';
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.test.tsx
index a265b2c998d39..a9a0dab044351 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.test.tsx
@@ -14,6 +14,7 @@ import { Credentials } from './credentials';
 import { EuiCopy, EuiLoadingContent, EuiPageContentBody } from '@elastic/eui';
 
 import { externalUrl } from '../../../shared/enterprise_search_url';
+import { CredentialsFlyout } from './credentials_flyout';
 
 describe('Credentials', () => {
   // Kea mocks
@@ -71,4 +72,16 @@ describe('Credentials', () => {
     button.props().onClick();
     expect(actions.showCredentialsForm).toHaveBeenCalledTimes(1);
   });
+
+  it('will render CredentialsFlyout if shouldShowCredentialsForm is true', () => {
+    setMockValues({ shouldShowCredentialsForm: true });
+    const wrapper = shallow(<Credentials />);
+    expect(wrapper.find(CredentialsFlyout)).toHaveLength(1);
+  });
+
+  it('will NOT render CredentialsFlyout if shouldShowCredentialsForm is false', () => {
+    setMockValues({ shouldShowCredentialsForm: false });
+    const wrapper = shallow(<Credentials />);
+    expect(wrapper.find(CredentialsFlyout)).toHaveLength(0);
+  });
 });
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.tsx
index b9a482ae462d5..c8eae8cc13f5f 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.tsx
@@ -24,16 +24,19 @@ import {
 import { i18n } from '@kbn/i18n';
 
 import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
+import { FlashMessages } from '../../../shared/flash_messages';
+
 import { CredentialsLogic } from './credentials_logic';
 import { externalUrl } from '../../../shared/enterprise_search_url/external_url';
 import { CredentialsList } from './credentials_list';
+import { CredentialsFlyout } from './credentials_flyout';
 
 export const Credentials: React.FC = () => {
   const { initializeCredentialsData, resetCredentials, showCredentialsForm } = useActions(
     CredentialsLogic
   );
 
-  const { dataLoading } = useValues(CredentialsLogic);
+  const { dataLoading, shouldShowCredentialsForm } = useValues(CredentialsLogic);
 
   useEffect(() => {
     initializeCredentialsData();
@@ -63,6 +66,7 @@ export const Credentials: React.FC = () => {
         </EuiPageHeaderSection>
       </EuiPageHeader>
       <EuiPageContentBody>
+        {shouldShowCredentialsForm && <CredentialsFlyout />}
         <EuiPanel className="eui-textCenter">
           <EuiTitle size="s">
             <h2>
@@ -120,7 +124,8 @@ export const Credentials: React.FC = () => {
             )}
           </EuiPageContentHeaderSection>
         </EuiPageContentHeader>
-        <EuiSpacer size="s" />
+        <EuiSpacer size="m" />
+        <FlashMessages />
         <EuiPanel>{!!dataLoading ? <EuiLoadingContent lines={3} /> : <CredentialsList />}</EuiPanel>
       </EuiPageContentBody>
     </>
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/body.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/body.test.tsx
new file mode 100644
index 0000000000000..e9217da163636
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/body.test.tsx
@@ -0,0 +1,101 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { setMockValues, setMockActions } from '../../../../__mocks__/kea.mock';
+
+import React from 'react';
+import { shallow } from 'enzyme';
+import { EuiFlyoutBody, EuiForm } from '@elastic/eui';
+
+import { ApiTokenTypes } from '../constants';
+import { defaultApiToken } from '../credentials_logic';
+
+import {
+  FormKeyName,
+  FormKeyType,
+  FormKeyReadWriteAccess,
+  FormKeyEngineAccess,
+  FormKeyUpdateWarning,
+} from './form_components';
+import { CredentialsFlyoutBody } from './body';
+
+describe('CredentialsFlyoutBody', () => {
+  const values = {
+    activeApiToken: defaultApiToken,
+    activeApiTokenExists: false,
+  };
+  const actions = {
+    onApiTokenChange: jest.fn(),
+  };
+
+  beforeEach(() => {
+    jest.clearAllMocks();
+    setMockValues(values);
+    setMockActions(actions);
+  });
+
+  it('renders', () => {
+    const wrapper = shallow(<CredentialsFlyoutBody />);
+
+    expect(wrapper.find(EuiFlyoutBody)).toHaveLength(1);
+    expect(wrapper.find(EuiForm)).toHaveLength(1);
+  });
+
+  it('shows the expected form components on default private key creation', () => {
+    const wrapper = shallow(<CredentialsFlyoutBody />);
+
+    expect(wrapper.find(FormKeyName)).toHaveLength(1);
+    expect(wrapper.find(FormKeyType)).toHaveLength(1);
+    expect(wrapper.find(FormKeyReadWriteAccess)).toHaveLength(1);
+    expect(wrapper.find(FormKeyEngineAccess)).toHaveLength(1);
+    expect(wrapper.find(FormKeyUpdateWarning)).toHaveLength(0);
+  });
+
+  it('does not show read-write access options for search keys', () => {
+    setMockValues({
+      ...values,
+      activeApiToken: {
+        ...defaultApiToken,
+        type: ApiTokenTypes.Search,
+      },
+    });
+    const wrapper = shallow(<CredentialsFlyoutBody />);
+
+    expect(wrapper.find(FormKeyReadWriteAccess)).toHaveLength(0);
+    expect(wrapper.find(FormKeyEngineAccess)).toHaveLength(1);
+  });
+
+  it('does not show read-write or engine access options for admin keys', () => {
+    setMockValues({
+      ...values,
+      activeApiToken: {
+        ...defaultApiToken,
+        type: ApiTokenTypes.Admin,
+      },
+    });
+    const wrapper = shallow(<CredentialsFlyoutBody />);
+
+    expect(wrapper.find(FormKeyReadWriteAccess)).toHaveLength(0);
+    expect(wrapper.find(FormKeyEngineAccess)).toHaveLength(0);
+  });
+
+  it('shows a warning if updating an existing key', () => {
+    setMockValues({ ...values, activeApiTokenExists: true });
+    const wrapper = shallow(<CredentialsFlyoutBody />);
+
+    expect(wrapper.find(FormKeyUpdateWarning)).toHaveLength(1);
+  });
+
+  it('calls onApiTokenChange on form submit', () => {
+    const wrapper = shallow(<CredentialsFlyoutBody />);
+
+    const preventDefault = jest.fn();
+    wrapper.find(EuiForm).simulate('submit', { preventDefault });
+
+    expect(preventDefault).toHaveBeenCalled();
+    expect(actions.onApiTokenChange).toHaveBeenCalled();
+  });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/body.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/body.tsx
new file mode 100644
index 0000000000000..0395c77cf9d89
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/body.tsx
@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { useValues, useActions } from 'kea';
+import { EuiFlyoutBody, EuiForm } from '@elastic/eui';
+
+import { FlashMessages } from '../../../../shared/flash_messages';
+import { CredentialsLogic } from '../credentials_logic';
+import { ApiTokenTypes } from '../constants';
+
+import {
+  FormKeyName,
+  FormKeyType,
+  FormKeyReadWriteAccess,
+  FormKeyEngineAccess,
+  FormKeyUpdateWarning,
+} from './form_components';
+
+export const CredentialsFlyoutBody: React.FC = () => {
+  const { onApiTokenChange } = useActions(CredentialsLogic);
+  const { activeApiToken, activeApiTokenExists } = useValues(CredentialsLogic);
+
+  return (
+    <EuiFlyoutBody>
+      <FlashMessages />
+      <EuiForm
+        onSubmit={(e) => {
+          e.preventDefault();
+          onApiTokenChange();
+        }}
+        component="form"
+      >
+        <FormKeyName />
+        <FormKeyType />
+        {activeApiToken.type === ApiTokenTypes.Private && <FormKeyReadWriteAccess />}
+        {activeApiToken.type !== ApiTokenTypes.Admin && <FormKeyEngineAccess />}
+      </EuiForm>
+      {activeApiTokenExists && <FormKeyUpdateWarning />}
+    </EuiFlyoutBody>
+  );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/footer.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/footer.test.tsx
new file mode 100644
index 0000000000000..c31546472b036
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/footer.test.tsx
@@ -0,0 +1,65 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { setMockValues, setMockActions } from '../../../../__mocks__/kea.mock';
+
+import React from 'react';
+import { shallow } from 'enzyme';
+import { EuiFlyoutFooter, EuiButtonEmpty } from '@elastic/eui';
+
+import { CredentialsFlyoutFooter } from './footer';
+
+describe('CredentialsFlyoutFooter', () => {
+  const values = {
+    activeApiTokenExists: false,
+  };
+  const actions = {
+    hideCredentialsForm: jest.fn(),
+    onApiTokenChange: jest.fn(),
+  };
+
+  beforeEach(() => {
+    jest.clearAllMocks();
+    setMockValues(values);
+    setMockActions(actions);
+  });
+
+  it('renders', () => {
+    const wrapper = shallow(<CredentialsFlyoutFooter />);
+    expect(wrapper.find(EuiFlyoutFooter)).toHaveLength(1);
+  });
+
+  it('closes the flyout', () => {
+    const wrapper = shallow(<CredentialsFlyoutFooter />);
+    const button = wrapper.find(EuiButtonEmpty);
+    button.simulate('click');
+    expect(button.prop('children')).toEqual('Close');
+    expect(actions.hideCredentialsForm).toHaveBeenCalled();
+  });
+
+  it('renders action button text for new tokens', () => {
+    const wrapper = shallow(<CredentialsFlyoutFooter />);
+    const button = wrapper.find('[data-test-subj="APIKeyActionButton"]');
+
+    expect(button.prop('children')).toEqual('Save');
+  });
+
+  it('renders action button text for existing tokens', () => {
+    setMockValues({ activeApiTokenExists: true });
+    const wrapper = shallow(<CredentialsFlyoutFooter />);
+    const button = wrapper.find('[data-test-subj="APIKeyActionButton"]');
+
+    expect(button.prop('children')).toEqual('Update');
+  });
+
+  it('calls onApiTokenChange on action button press', () => {
+    const wrapper = shallow(<CredentialsFlyoutFooter />);
+    const button = wrapper.find('[data-test-subj="APIKeyActionButton"]');
+    button.simulate('click');
+
+    expect(actions.onApiTokenChange).toHaveBeenCalled();
+  });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/footer.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/footer.tsx
new file mode 100644
index 0000000000000..e59a75a578ba4
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/footer.tsx
@@ -0,0 +1,54 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { useValues, useActions } from 'kea';
+import {
+  EuiFlyoutFooter,
+  EuiFlexGroup,
+  EuiFlexItem,
+  EuiButtonEmpty,
+  EuiButton,
+} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+import { CredentialsLogic } from '../credentials_logic';
+
+export const CredentialsFlyoutFooter: React.FC = () => {
+  const { hideCredentialsForm, onApiTokenChange } = useActions(CredentialsLogic);
+  const { activeApiTokenExists } = useValues(CredentialsLogic);
+
+  return (
+    <EuiFlyoutFooter>
+      <EuiFlexGroup justifyContent="spaceBetween">
+        <EuiFlexItem grow={false}>
+          <EuiButtonEmpty iconType="cross" onClick={hideCredentialsForm}>
+            {i18n.translate('xpack.enterpriseSearch.appSearch.credentials.flyout.closeText', {
+              defaultMessage: 'Close',
+            })}
+          </EuiButtonEmpty>
+        </EuiFlexItem>
+        <EuiFlexItem grow={false}>
+          <EuiButton
+            onClick={onApiTokenChange}
+            fill={true}
+            color="secondary"
+            iconType="check"
+            data-test-subj="APIKeyActionButton"
+          >
+            {activeApiTokenExists
+              ? i18n.translate('xpack.enterpriseSearch.appSearch.credentials.flyout.updateText', {
+                  defaultMessage: 'Update',
+                })
+              : i18n.translate('xpack.enterpriseSearch.appSearch.credentials.flyout.saveText', {
+                  defaultMessage: 'Save',
+                })}
+          </EuiButton>
+        </EuiFlexItem>
+      </EuiFlexGroup>
+    </EuiFlyoutFooter>
+  );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/index.ts
new file mode 100644
index 0000000000000..ad39717ff8979
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/index.ts
@@ -0,0 +1,11 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { FormKeyName } from './key_name';
+export { FormKeyType } from './key_type';
+export { FormKeyReadWriteAccess } from './key_read_write_access';
+export { FormKeyEngineAccess } from './key_engine_access';
+export { FormKeyUpdateWarning } from './key_update_warning';
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.test.tsx
new file mode 100644
index 0000000000000..b4b092f17a6aa
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.test.tsx
@@ -0,0 +1,135 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { setMockValues, setMockActions } from '../../../../../__mocks__/kea.mock';
+
+import React from 'react';
+import { shallow } from 'enzyme';
+import { EuiRadio, EuiCheckbox } from '@elastic/eui';
+
+import { FormKeyEngineAccess, EngineSelection } from './key_engine_access';
+
+describe('FormKeyEngineAccess', () => {
+  const values = {
+    myRole: { canAccessAllEngines: true },
+    fullEngineAccessChecked: true,
+  };
+  const actions = {
+    setAccessAllEngines: jest.fn(),
+  };
+
+  beforeEach(() => {
+    jest.clearAllMocks();
+    setMockValues(values);
+    setMockActions(actions);
+  });
+
+  it('renders', () => {
+    const wrapper = shallow(<FormKeyEngineAccess />);
+
+    expect(wrapper.find(EuiRadio)).toHaveLength(2);
+    expect(wrapper.find(EngineSelection)).toHaveLength(0);
+  });
+
+  it('hides the full access radio option if the user does not have access to all engines', () => {
+    setMockValues({
+      ...values,
+      myRole: { canAccessAllEngines: false },
+    });
+    const wrapper = shallow(<FormKeyEngineAccess />);
+
+    expect(wrapper.find('#all_engines').prop('hidden')).toEqual(true);
+  });
+
+  it('controls the checked values for access radios', () => {
+    setMockValues({
+      ...values,
+      fullEngineAccessChecked: true,
+    });
+    const wrapper = shallow(<FormKeyEngineAccess />);
+
+    expect(wrapper.find('#all_engines').prop('checked')).toEqual(true);
+    expect(wrapper.find('#all_engines').prop('value')).toEqual('true');
+    expect(wrapper.find('#specific_engines').prop('checked')).toEqual(false);
+    expect(wrapper.find('#specific_engines').prop('value')).toEqual('false');
+
+    setMockValues({
+      ...values,
+      fullEngineAccessChecked: false,
+    });
+    wrapper.setProps({}); // Re-render
+
+    expect(wrapper.find('#all_engines').prop('checked')).toEqual(false);
+    expect(wrapper.find('#all_engines').prop('value')).toEqual('false');
+    expect(wrapper.find('#specific_engines').prop('checked')).toEqual(true);
+    expect(wrapper.find('#specific_engines').prop('value')).toEqual('true');
+  });
+
+  it('calls setAccessAllEngines when the radios are changed', () => {
+    const wrapper = shallow(<FormKeyEngineAccess />);
+
+    wrapper.find('#all_engines').simulate('change');
+    expect(actions.setAccessAllEngines).toHaveBeenCalledWith(true);
+
+    wrapper.find('#specific_engines').simulate('change');
+    expect(actions.setAccessAllEngines).toHaveBeenCalledWith(false);
+  });
+
+  it('displays the engine selection panel if the limited access radio is selected', () => {
+    setMockValues({
+      ...values,
+      fullEngineAccessChecked: false,
+    });
+    const wrapper = shallow(<FormKeyEngineAccess />);
+
+    expect(wrapper.find(EngineSelection)).toHaveLength(1);
+  });
+});
+
+describe('EngineSelection', () => {
+  const values = {
+    activeApiToken: { engines: [] },
+    engines: [{ name: 'engine1' }, { name: 'engine2' }, { name: 'engine3' }],
+  };
+  const actions = {
+    onEngineSelect: jest.fn(),
+  };
+
+  beforeEach(() => {
+    jest.clearAllMocks();
+    setMockValues(values);
+    setMockActions(actions);
+  });
+
+  it('renders', () => {
+    const wrapper = shallow(<EngineSelection />);
+
+    expect(wrapper.find('h4').text()).toEqual('Select Engines');
+    expect(wrapper.find(EuiCheckbox)).toHaveLength(3);
+    expect(wrapper.find(EuiCheckbox).first().prop('label')).toEqual('engine1');
+  });
+
+  it('controls the engines checked state', () => {
+    setMockValues({
+      ...values,
+      activeApiToken: { engines: ['engine3'] },
+    });
+    const wrapper = shallow(<EngineSelection />);
+
+    expect(wrapper.find(EuiCheckbox).first().prop('checked')).toEqual(false);
+    expect(wrapper.find(EuiCheckbox).last().prop('checked')).toEqual(true);
+  });
+
+  it('calls onEngineSelect when the checkboxes are changed', () => {
+    const wrapper = shallow(<EngineSelection />);
+
+    wrapper.find(EuiCheckbox).first().simulate('change');
+    expect(actions.onEngineSelect).toHaveBeenCalledWith('engine1');
+
+    wrapper.find(EuiCheckbox).last().simulate('change');
+    expect(actions.onEngineSelect).toHaveBeenCalledWith('engine3');
+  });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.tsx
new file mode 100644
index 0000000000000..88e345d0f9966
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.tsx
@@ -0,0 +1,133 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { useValues, useActions } from 'kea';
+import {
+  EuiFormRow,
+  EuiRadio,
+  EuiCheckbox,
+  EuiText,
+  EuiTitle,
+  EuiSpacer,
+  EuiPanel,
+} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+import { AppLogic } from '../../../../app_logic';
+import { CredentialsLogic } from '../../credentials_logic';
+
+export const FormKeyEngineAccess: React.FC = () => {
+  const { myRole } = useValues(AppLogic);
+  const { setAccessAllEngines } = useActions(CredentialsLogic);
+  const { fullEngineAccessChecked } = useValues(CredentialsLogic);
+
+  return (
+    <>
+      <EuiSpacer />
+      <EuiFormRow
+        label={i18n.translate(
+          'xpack.enterpriseSearch.appSearch.credentials.formEngineAccess.label',
+          { defaultMessage: 'Engine Access Control' }
+        )}
+      >
+        <>
+          <EuiRadio
+            name="engine_access"
+            id="all_engines"
+            label={
+              <>
+                <EuiTitle size="xxs">
+                  <h3>
+                    {i18n.translate(
+                      'xpack.enterpriseSearch.appSearch.credentials.formEngineAccess.fullAccess.label',
+                      { defaultMessage: 'Full Engine Access' }
+                    )}
+                  </h3>
+                </EuiTitle>
+                <EuiText size="s">
+                  {i18n.translate(
+                    'xpack.enterpriseSearch.appSearch.credentials.formEngineAccess.fullAccess.helpText',
+                    { defaultMessage: 'Access to all current and future Engines.' }
+                  )}
+                </EuiText>
+              </>
+            }
+            hidden={!myRole.canAccessAllEngines}
+            checked={fullEngineAccessChecked}
+            value={fullEngineAccessChecked.toString()}
+            onChange={() => setAccessAllEngines(true)}
+          />
+          <EuiSpacer size="s" />
+          <EuiRadio
+            name="engine_access"
+            id="specific_engines"
+            label={
+              <>
+                <EuiTitle size="xxs">
+                  <h3>
+                    {i18n.translate(
+                      'xpack.enterpriseSearch.appSearch.credentials.formEngineAccess.limitedAccess.label',
+                      { defaultMessage: 'Limited Engine Access' }
+                    )}
+                  </h3>
+                </EuiTitle>
+                <EuiText size="s">
+                  {i18n.translate(
+                    'xpack.enterpriseSearch.appSearch.credentials.formEngineAccess.limitedAccess.helpText',
+                    { defaultMessage: 'Limit key access to specific Engines.' }
+                  )}
+                </EuiText>
+              </>
+            }
+            checked={!fullEngineAccessChecked}
+            value={(!fullEngineAccessChecked).toString()}
+            onChange={() => setAccessAllEngines(false)}
+          />
+        </>
+      </EuiFormRow>
+      {!fullEngineAccessChecked && <EngineSelection />}
+    </>
+  );
+};
+
+export const EngineSelection: React.FC = () => {
+  const { onEngineSelect } = useActions(CredentialsLogic);
+  const { activeApiToken, engines } = useValues(CredentialsLogic);
+
+  return (
+    <>
+      <EuiSpacer size="s" />
+      <EuiPanel>
+        <EuiTitle size="xs">
+          <h4>
+            {i18n.translate(
+              'xpack.enterpriseSearch.appSearch.credentials.formEngineAccess.engineAccess.label',
+              { defaultMessage: 'Select Engines' }
+            )}
+          </h4>
+        </EuiTitle>
+        <EuiText>
+          {i18n.translate(
+            'xpack.enterpriseSearch.appSearch.credentials.formEngineAccess.engineAccess.helpText',
+            { defaultMessage: 'Engines which the key can access:' }
+          )}
+        </EuiText>
+        <EuiSpacer size="s" />
+        {engines.map((engine) => (
+          <EuiCheckbox
+            key={engine.name}
+            name={engine.name}
+            id={`engine_${engine.name}`}
+            label={engine.name}
+            checked={!!activeApiToken?.engines?.includes(engine.name)}
+            onChange={() => onEngineSelect(engine.name)}
+          />
+        ))}
+      </EuiPanel>
+    </>
+  );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_name.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_name.test.tsx
new file mode 100644
index 0000000000000..87f0f843dfa67
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_name.test.tsx
@@ -0,0 +1,88 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { setMockValues, setMockActions } from '../../../../../__mocks__/kea.mock';
+
+import React from 'react';
+import { shallow } from 'enzyme';
+import { EuiFieldText, EuiFormRow } from '@elastic/eui';
+
+import { FormKeyName } from './';
+
+describe('FormKeyName', () => {
+  const values = {
+    activeApiToken: { name: '' },
+    activeApiTokenRawName: '',
+    activeApiTokenExists: false,
+  };
+  const actions = {
+    setNameInputBlurred: jest.fn(),
+    setTokenName: jest.fn(),
+  };
+
+  beforeEach(() => {
+    jest.clearAllMocks();
+    setMockValues(values);
+    setMockActions(actions);
+  });
+
+  it('renders', () => {
+    const wrapper = shallow(<FormKeyName />);
+
+    expect(wrapper.find(EuiFieldText)).toHaveLength(1);
+    expect(wrapper.find(EuiFieldText).prop('placeholder')).toEqual('i.e., my-engine-key');
+    expect(wrapper.find(EuiFieldText).prop('value')).toEqual('');
+    expect(wrapper.find(EuiFieldText).prop('disabled')).toEqual(false);
+    expect(wrapper.find(EuiFormRow).prop('helpText')).toEqual('');
+  });
+
+  it('shows help text if the raw name does not match the expected name', () => {
+    setMockValues({
+      ...values,
+      activeApiToken: { name: 'my-engine-key' },
+      activeApiTokenRawName: 'my engine key!!',
+    });
+    const wrapper = shallow(<FormKeyName />);
+
+    expect(wrapper.find(EuiFormRow).prop('helpText')).toEqual(
+      'Your key will be named: my-engine-key'
+    );
+  });
+
+  it('controls the input value', () => {
+    setMockValues({
+      ...values,
+      activeApiTokenRawName: 'test',
+    });
+    const wrapper = shallow(<FormKeyName />);
+
+    expect(wrapper.find(EuiFieldText).prop('value')).toEqual('test');
+  });
+
+  it('disables the input if editing an existing key', () => {
+    setMockValues({
+      ...values,
+      activeApiTokenExists: true,
+    });
+    const wrapper = shallow(<FormKeyName />);
+
+    expect(wrapper.find(EuiFieldText).prop('disabled')).toEqual(true);
+  });
+
+  it('calls setTokenName when the input value is changed', () => {
+    const wrapper = shallow(<FormKeyName />);
+    wrapper.find(EuiFieldText).simulate('change', { target: { value: 'changed' } });
+
+    expect(actions.setTokenName).toHaveBeenCalledWith('changed');
+  });
+
+  it('calls setNameInputBlurred when the user stops focusing the input', () => {
+    const wrapper = shallow(<FormKeyName />);
+    wrapper.find(EuiFieldText).simulate('blur');
+
+    expect(actions.setNameInputBlurred).toHaveBeenCalledWith(true);
+  });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_name.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_name.tsx
new file mode 100644
index 0000000000000..fb8de2b244ecc
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_name.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;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { useValues, useActions } from 'kea';
+import { EuiFormRow, EuiFieldText } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+import { CredentialsLogic } from '../../credentials_logic';
+
+export const FormKeyName: React.FC = () => {
+  const { setNameInputBlurred, setTokenName } = useActions(CredentialsLogic);
+  const {
+    activeApiToken: { name },
+    activeApiTokenRawName: rawName,
+    activeApiTokenExists,
+  } = useValues(CredentialsLogic);
+
+  return (
+    <EuiFormRow
+      label={i18n.translate('xpack.enterpriseSearch.appSearch.credentials.formName.label', {
+        defaultMessage: 'Key name',
+      })}
+      helpText={
+        !!name && name !== rawName
+          ? i18n.translate('xpack.enterpriseSearch.appSearch.credentials.formName.helpText', {
+              defaultMessage: 'Your key will be named: {name}',
+              values: { name },
+            })
+          : ''
+      }
+      fullWidth
+    >
+      <EuiFieldText
+        name="raw_name"
+        id="raw_name"
+        placeholder={i18n.translate(
+          'xpack.enterpriseSearch.appSearch.credentials.formName.placeholder',
+          { defaultMessage: 'i.e., my-engine-key' }
+        )}
+        data-test-subj="APIKeyField"
+        value={rawName}
+        onChange={(e) => setTokenName(e.target.value)}
+        onBlur={() => setNameInputBlurred(true)}
+        autoComplete="off"
+        maxLength={64}
+        disabled={activeApiTokenExists}
+        required
+        fullWidth
+        autoFocus
+      />
+    </EuiFormRow>
+  );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_read_write_access.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_read_write_access.test.tsx
new file mode 100644
index 0000000000000..2f1be1b07cbe1
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_read_write_access.test.tsx
@@ -0,0 +1,67 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { setMockValues, setMockActions } from '../../../../../__mocks__/kea.mock';
+
+import React from 'react';
+import { shallow } from 'enzyme';
+import { EuiCheckbox } from '@elastic/eui';
+
+import { FormKeyReadWriteAccess } from './';
+
+describe('FormKeyReadWriteAccess', () => {
+  const values = {
+    activeApiToken: { read: false, write: false },
+  };
+  const actions = {
+    setTokenReadWrite: jest.fn(),
+  };
+
+  beforeEach(() => {
+    jest.clearAllMocks();
+    setMockValues(values);
+    setMockActions(actions);
+  });
+
+  it('renders', () => {
+    const wrapper = shallow(<FormKeyReadWriteAccess />);
+
+    expect(wrapper.find('h3').text()).toEqual('Read and Write Access Levels');
+    expect(wrapper.find(EuiCheckbox)).toHaveLength(2);
+  });
+
+  it('controls the checked state for the read checkbox', () => {
+    setMockValues({
+      ...values,
+      activeApiToken: { read: true, write: false },
+    });
+    const wrapper = shallow(<FormKeyReadWriteAccess />);
+
+    expect(wrapper.find('#read').prop('checked')).toEqual(true);
+    expect(wrapper.find('#write').prop('checked')).toEqual(false);
+  });
+
+  it('controls the checked state for the write checkbox', () => {
+    setMockValues({
+      ...values,
+      activeApiToken: { read: false, write: true },
+    });
+    const wrapper = shallow(<FormKeyReadWriteAccess />);
+
+    expect(wrapper.find('#read').prop('checked')).toEqual(false);
+    expect(wrapper.find('#write').prop('checked')).toEqual(true);
+  });
+
+  it('calls setTokenReadWrite when the checkboxes are changed', () => {
+    const wrapper = shallow(<FormKeyReadWriteAccess />);
+
+    wrapper.find('#read').simulate('change', { target: { name: 'read', checked: true } });
+    expect(actions.setTokenReadWrite).toHaveBeenCalledWith({ name: 'read', checked: true });
+
+    wrapper.find('#write').simulate('change', { target: { name: 'write', checked: false } });
+    expect(actions.setTokenReadWrite).toHaveBeenCalledWith({ name: 'write', checked: false });
+  });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_read_write_access.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_read_write_access.tsx
new file mode 100644
index 0000000000000..a02b00b6ad377
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_read_write_access.tsx
@@ -0,0 +1,59 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { useValues, useActions } from 'kea';
+import { EuiCheckbox, EuiText, EuiTitle, EuiSpacer, EuiPanel } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+import { CredentialsLogic } from '../../credentials_logic';
+import { ITokenReadWrite } from '../../types';
+
+export const FormKeyReadWriteAccess: React.FC = () => {
+  const { setTokenReadWrite } = useActions(CredentialsLogic);
+  const { activeApiToken } = useValues(CredentialsLogic);
+
+  return (
+    <>
+      <EuiSpacer size="s" />
+      <EuiPanel>
+        <EuiTitle size="xs">
+          <h3>
+            {i18n.translate('xpack.enterpriseSearch.appSearch.credentials.formReadWrite.label', {
+              defaultMessage: 'Read and Write Access Levels',
+            })}
+          </h3>
+        </EuiTitle>
+        <EuiText>
+          {i18n.translate('xpack.enterpriseSearch.appSearch.credentials.formReadWrite.helpText', {
+            defaultMessage: 'Only applies to Private API Keys.',
+          })}
+        </EuiText>
+        <EuiSpacer size="s" />
+        <EuiCheckbox
+          name="read"
+          id="read"
+          checked={activeApiToken.read}
+          onChange={(e) => setTokenReadWrite(e.target as ITokenReadWrite)}
+          label={i18n.translate(
+            'xpack.enterpriseSearch.appSearch.credentials.formReadWrite.readLabel',
+            { defaultMessage: 'Read Access' }
+          )}
+        />
+        <EuiCheckbox
+          name="write"
+          id="write"
+          checked={activeApiToken.write}
+          onChange={(e) => setTokenReadWrite(e.target as ITokenReadWrite)}
+          label={i18n.translate(
+            'xpack.enterpriseSearch.appSearch.credentials.formReadWrite.writeLabel',
+            { defaultMessage: 'Write Access' }
+          )}
+        />
+      </EuiPanel>
+    </>
+  );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_type.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_type.test.tsx
new file mode 100644
index 0000000000000..d07a705b2d90b
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_type.test.tsx
@@ -0,0 +1,80 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { setMockValues, setMockActions } from '../../../../../__mocks__/kea.mock';
+
+import React from 'react';
+import { shallow } from 'enzyme';
+import { EuiSelect } from '@elastic/eui';
+
+import { ApiTokenTypes, TOKEN_TYPE_INFO } from '../../constants';
+import { FormKeyType } from './';
+
+describe('FormKeyType', () => {
+  const values = {
+    myRole: { credentialTypes: ['search', 'private', 'admin'] },
+    activeApiToken: { type: ApiTokenTypes.Private },
+    activeApiTokenExists: false,
+  };
+  const actions = {
+    setTokenType: jest.fn(),
+  };
+
+  beforeEach(() => {
+    jest.clearAllMocks();
+    setMockValues(values);
+    setMockActions(actions);
+  });
+
+  it('renders', () => {
+    const wrapper = shallow(<FormKeyType />);
+
+    expect(wrapper.find(EuiSelect)).toHaveLength(1);
+    expect(wrapper.find(EuiSelect).prop('placeholder')).toEqual('Select a key type');
+    expect(wrapper.find(EuiSelect).prop('options')).toEqual(TOKEN_TYPE_INFO);
+    expect(wrapper.find(EuiSelect).prop('value')).toEqual(ApiTokenTypes.Private);
+    expect(wrapper.find(EuiSelect).prop('disabled')).toEqual(false);
+  });
+
+  it('only shows the type options that the user has access to', () => {
+    setMockValues({
+      ...values,
+      myRole: { credentialTypes: ['search'] },
+    });
+    const wrapper = shallow(<FormKeyType />);
+
+    expect(wrapper.find(EuiSelect).prop('options')).toEqual([
+      expect.objectContaining({ value: ApiTokenTypes.Search }),
+    ]);
+  });
+
+  it('controls the select value', () => {
+    setMockValues({
+      ...values,
+      activeApiToken: { type: ApiTokenTypes.Search },
+    });
+    const wrapper = shallow(<FormKeyType />);
+
+    expect(wrapper.find(EuiSelect).prop('value')).toEqual(ApiTokenTypes.Search);
+  });
+
+  it('disables the select if editing an existing key', () => {
+    setMockValues({
+      ...values,
+      activeApiTokenExists: true,
+    });
+    const wrapper = shallow(<FormKeyType />);
+
+    expect(wrapper.find(EuiSelect).prop('disabled')).toEqual(true);
+  });
+
+  it('calls setTokenType when the select value is changed', () => {
+    const wrapper = shallow(<FormKeyType />);
+    wrapper.find(EuiSelect).simulate('change', { target: { value: ApiTokenTypes.Admin } });
+
+    expect(actions.setTokenType).toHaveBeenCalledWith(ApiTokenTypes.Admin);
+  });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_type.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_type.tsx
new file mode 100644
index 0000000000000..7268c12614e8b
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_type.tsx
@@ -0,0 +1,63 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { useValues, useActions } from 'kea';
+import { EuiFormRow, EuiSelect, EuiText, EuiLink } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+import { AppLogic } from '../../../../app_logic';
+import { CredentialsLogic } from '../../credentials_logic';
+import { TOKEN_TYPE_DESCRIPTION, TOKEN_TYPE_INFO, DOCS_HREF } from '../../constants';
+
+export const FormKeyType: React.FC = () => {
+  const { myRole } = useValues(AppLogic);
+  const { setTokenType } = useActions(CredentialsLogic);
+  const { activeApiToken, activeApiTokenExists } = useValues(CredentialsLogic);
+
+  const tokenDescription = TOKEN_TYPE_DESCRIPTION[activeApiToken.type];
+  const tokenOptions = TOKEN_TYPE_INFO.filter((typeInfo) =>
+    myRole?.credentialTypes?.includes(typeInfo.value)
+  );
+
+  return (
+    <EuiFormRow
+      label={i18n.translate('xpack.enterpriseSearch.appSearch.credentials.formType.label', {
+        defaultMessage: 'Key type',
+      })}
+      fullWidth
+      helpText={
+        <EuiText size="xs">
+          <p>
+            <strong>{tokenDescription}</strong>{' '}
+            <EuiLink href={DOCS_HREF}>
+              {i18n.translate('xpack.enterpriseSearch.appSearch.credentials.documentationLink1', {
+                defaultMessage: 'Visit the documentation',
+              })}
+            </EuiLink>{' '}
+            {i18n.translate('xpack.enterpriseSearch.appSearch.credentials.documentationLink2', {
+              defaultMessage: 'to learn more about keys.',
+            })}
+          </p>
+        </EuiText>
+      }
+    >
+      <EuiSelect
+        name="token_type"
+        options={tokenOptions}
+        value={activeApiToken.type}
+        onChange={(e) => setTokenType(e.target.value)}
+        placeholder={i18n.translate(
+          'xpack.enterpriseSearch.appSearch.credentials.formType.placeholder',
+          { defaultMessage: 'Select a key type' }
+        )}
+        disabled={activeApiTokenExists}
+        required
+        fullWidth
+      />
+    </EuiFormRow>
+  );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_update_warning.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_update_warning.test.tsx
new file mode 100644
index 0000000000000..c0ff892c220c7
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_update_warning.test.tsx
@@ -0,0 +1,18 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { shallow } from 'enzyme';
+import { EuiCallOut } from '@elastic/eui';
+
+import { FormKeyUpdateWarning } from './';
+
+describe('FormKeyUpdateWarning', () => {
+  it('renders', () => {
+    const wrapper = shallow(<FormKeyUpdateWarning />);
+    expect(wrapper.find(EuiCallOut)).toHaveLength(1);
+  });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_update_warning.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_update_warning.tsx
new file mode 100644
index 0000000000000..7e7aaa583325d
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_update_warning.tsx
@@ -0,0 +1,29 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { EuiSpacer, EuiCallOut } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+export const FormKeyUpdateWarning: React.FC = () => (
+  <>
+    <EuiSpacer />
+    <EuiCallOut
+      title={i18n.translate('xpack.enterpriseSearch.appSearch.credentials.updateWarningTitle', {
+        defaultMessage: 'Proceed with caution!',
+      })}
+      color="warning"
+      iconType="alert"
+    >
+      <p>
+        {i18n.translate('xpack.enterpriseSearch.appSearch.credentials.updateWarning', {
+          defaultMessage:
+            'Existing API keys may be shared between users. Changing permissions for this key will affect all users who have access to this key.',
+        })}
+      </p>
+    </EuiCallOut>
+  </>
+);
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/header.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/header.test.tsx
new file mode 100644
index 0000000000000..a8d9505136faa
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/header.test.tsx
@@ -0,0 +1,55 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { setMockValues } from '../../../../__mocks__/kea.mock';
+
+import React from 'react';
+import { shallow } from 'enzyme';
+import { EuiFlyoutHeader } from '@elastic/eui';
+
+import { ApiTokenTypes } from '../constants';
+import { IApiToken } from '../types';
+
+import { CredentialsFlyoutHeader } from './header';
+
+describe('CredentialsFlyoutHeader', () => {
+  const apiToken: IApiToken = {
+    name: '',
+    type: ApiTokenTypes.Private,
+    read: true,
+    write: true,
+    access_all_engines: true,
+  };
+  const values = {
+    activeApiToken: apiToken,
+  };
+
+  beforeEach(() => {
+    jest.clearAllMocks();
+    setMockValues(values);
+  });
+
+  it('renders', () => {
+    const wrapper = shallow(<CredentialsFlyoutHeader />);
+
+    expect(wrapper.find(EuiFlyoutHeader)).toHaveLength(1);
+    expect(wrapper.find('h2').prop('id')).toEqual('credentialsFlyoutTitle');
+    expect(wrapper.find('h2').prop('children')).toEqual('Create a new key');
+  });
+
+  it('changes the title text if editing an existing token', () => {
+    setMockValues({
+      activeApiToken: {
+        ...apiToken,
+        id: 'some-id',
+        name: 'search-key',
+      },
+    });
+    const wrapper = shallow(<CredentialsFlyoutHeader />);
+
+    expect(wrapper.find('h2').prop('children')).toEqual('Update search-key');
+  });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/header.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/header.tsx
new file mode 100644
index 0000000000000..f208cd1c5918f
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/header.tsx
@@ -0,0 +1,34 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { useValues } from 'kea';
+import { EuiFlyoutHeader, EuiTitle } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+import { CredentialsLogic } from '../credentials_logic';
+import { FLYOUT_ARIA_LABEL_ID } from '../constants';
+
+export const CredentialsFlyoutHeader: React.FC = () => {
+  const { activeApiToken } = useValues(CredentialsLogic);
+
+  return (
+    <EuiFlyoutHeader hasBorder={true}>
+      <EuiTitle size="m">
+        <h2 id={FLYOUT_ARIA_LABEL_ID}>
+          {activeApiToken.id
+            ? i18n.translate('xpack.enterpriseSearch.appSearch.credentials.flyout.updateTitle', {
+                defaultMessage: 'Update {tokenName}',
+                values: { tokenName: activeApiToken.name },
+              })
+            : i18n.translate('xpack.enterpriseSearch.appSearch.credentials.flyout.createTitle', {
+                defaultMessage: 'Create a new key',
+              })}
+        </h2>
+      </EuiTitle>
+    </EuiFlyoutHeader>
+  );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/index.test.tsx
new file mode 100644
index 0000000000000..16b669c530012
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/index.test.tsx
@@ -0,0 +1,33 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { setMockActions } from '../../../../__mocks__/kea.mock';
+
+import React from 'react';
+import { shallow } from 'enzyme';
+import { EuiFlyout } from '@elastic/eui';
+
+import { CredentialsFlyout } from './';
+
+describe('CredentialsFlyout', () => {
+  const actions = {
+    hideCredentialsForm: jest.fn(),
+  };
+
+  beforeEach(() => {
+    jest.clearAllMocks();
+    setMockActions(actions);
+  });
+
+  it('renders', () => {
+    const wrapper = shallow(<CredentialsFlyout />);
+    const flyout = wrapper.find(EuiFlyout);
+
+    expect(flyout).toHaveLength(1);
+    expect(flyout.prop('aria-labelledby')).toEqual('credentialsFlyoutTitle');
+    expect(flyout.prop('onClose')).toEqual(actions.hideCredentialsForm);
+  });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/index.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/index.tsx
new file mode 100644
index 0000000000000..602a5250716c3
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/index.tsx
@@ -0,0 +1,35 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { useActions } from 'kea';
+import { EuiPortal, EuiFlyout } from '@elastic/eui';
+
+import { CredentialsLogic } from '../credentials_logic';
+import { FLYOUT_ARIA_LABEL_ID } from '../constants';
+import { CredentialsFlyoutHeader } from './header';
+import { CredentialsFlyoutBody } from './body';
+import { CredentialsFlyoutFooter } from './footer';
+
+export const CredentialsFlyout: React.FC = () => {
+  const { hideCredentialsForm } = useActions(CredentialsLogic);
+
+  return (
+    <EuiPortal>
+      <EuiFlyout
+        onClose={hideCredentialsForm}
+        hideCloseButton={true}
+        ownFocus={true}
+        aria-labelledby={FLYOUT_ARIA_LABEL_ID}
+        size="s"
+      >
+        <CredentialsFlyoutHeader />
+        <CredentialsFlyoutBody />
+        <CredentialsFlyoutFooter />
+      </EuiFlyout>
+    </EuiPortal>
+  );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts
index 11b1253332cb2..de79862b540ba 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts
@@ -6,17 +6,33 @@
 
 import { resetContext } from 'kea';
 
-import { CredentialsLogic } from './credentials_logic';
-import { ApiTokenTypes } from './constants';
-
+import { mockHttpValues } from '../../../__mocks__';
 jest.mock('../../../shared/http', () => ({
-  HttpLogic: { values: { http: { get: jest.fn(), delete: jest.fn() } } },
+  HttpLogic: { values: mockHttpValues },
 }));
-import { HttpLogic } from '../../../shared/http';
+const { http } = mockHttpValues;
+
 jest.mock('../../../shared/flash_messages', () => ({
+  FlashMessagesLogic: { actions: { clearFlashMessages: jest.fn() } },
+  setSuccessMessage: jest.fn(),
   flashAPIErrors: jest.fn(),
 }));
-import { flashAPIErrors } from '../../../shared/flash_messages';
+import {
+  FlashMessagesLogic,
+  setSuccessMessage,
+  flashAPIErrors,
+} from '../../../shared/flash_messages';
+
+jest.mock('../../app_logic', () => ({
+  AppLogic: {
+    selectors: { myRole: jest.fn(() => ({})) },
+    values: { myRole: jest.fn(() => ({})) },
+  },
+}));
+import { AppLogic } from '../../app_logic';
+
+import { ApiTokenTypes } from './constants';
+import { CredentialsLogic } from './credentials_logic';
 
 describe('CredentialsLogic', () => {
   const DEFAULT_VALUES = {
@@ -38,6 +54,7 @@ describe('CredentialsLogic', () => {
     meta: {},
     nameInputBlurred: false,
     shouldShowCredentialsForm: false,
+    fullEngineAccessChecked: false,
   };
 
   const mount = (defaults?: object) => {
@@ -952,6 +969,13 @@ describe('CredentialsLogic', () => {
           });
         });
       });
+
+      describe('listener side-effects', () => {
+        it('should clear flashMessages whenever the credentials form flyout is opened', () => {
+          CredentialsLogic.actions.showCredentialsForm();
+          expect(FlashMessagesLogic.actions.clearFlashMessages).toHaveBeenCalled();
+        });
+      });
     });
 
     describe('hideCredentialsForm', () => {
@@ -1068,10 +1092,10 @@ describe('CredentialsLogic', () => {
         mount();
         jest.spyOn(CredentialsLogic.actions, 'setCredentialsData').mockImplementationOnce(() => {});
         const promise = Promise.resolve({ meta, results });
-        (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise);
+        http.get.mockReturnValue(promise);
 
         CredentialsLogic.actions.fetchCredentials(2);
-        expect(HttpLogic.values.http.get).toHaveBeenCalledWith('/api/app_search/credentials', {
+        expect(http.get).toHaveBeenCalledWith('/api/app_search/credentials', {
           query: {
             'page[current]': 2,
           },
@@ -1083,7 +1107,7 @@ describe('CredentialsLogic', () => {
       it('handles errors', async () => {
         mount();
         const promise = Promise.reject('An error occured');
-        (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise);
+        http.get.mockReturnValue(promise);
 
         CredentialsLogic.actions.fetchCredentials();
         try {
@@ -1101,12 +1125,10 @@ describe('CredentialsLogic', () => {
           .spyOn(CredentialsLogic.actions, 'setCredentialsDetails')
           .mockImplementationOnce(() => {});
         const promise = Promise.resolve(credentialsDetails);
-        (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise);
+        http.get.mockReturnValue(promise);
 
         CredentialsLogic.actions.fetchDetails();
-        expect(HttpLogic.values.http.get).toHaveBeenCalledWith(
-          '/api/app_search/credentials/details'
-        );
+        expect(http.get).toHaveBeenCalledWith('/api/app_search/credentials/details');
         await promise;
         expect(CredentialsLogic.actions.setCredentialsDetails).toHaveBeenCalledWith(
           credentialsDetails
@@ -1116,7 +1138,7 @@ describe('CredentialsLogic', () => {
       it('handles errors', async () => {
         mount();
         const promise = Promise.reject('An error occured');
-        (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise);
+        http.get.mockReturnValue(promise);
 
         CredentialsLogic.actions.fetchDetails();
         try {
@@ -1134,20 +1156,19 @@ describe('CredentialsLogic', () => {
         mount();
         jest.spyOn(CredentialsLogic.actions, 'onApiKeyDelete').mockImplementationOnce(() => {});
         const promise = Promise.resolve();
-        (HttpLogic.values.http.delete as jest.Mock).mockReturnValue(promise);
+        http.delete.mockReturnValue(promise);
 
         CredentialsLogic.actions.deleteApiKey(tokenName);
-        expect(HttpLogic.values.http.delete).toHaveBeenCalledWith(
-          `/api/app_search/credentials/${tokenName}`
-        );
+        expect(http.delete).toHaveBeenCalledWith(`/api/app_search/credentials/${tokenName}`);
         await promise;
         expect(CredentialsLogic.actions.onApiKeyDelete).toHaveBeenCalledWith(tokenName);
+        expect(setSuccessMessage).toHaveBeenCalled();
       });
 
       it('handles errors', async () => {
         mount();
         const promise = Promise.reject('An error occured');
-        (HttpLogic.values.http.delete as jest.Mock).mockReturnValue(promise);
+        http.delete.mockReturnValue(promise);
 
         CredentialsLogic.actions.deleteApiKey(tokenName);
         try {
@@ -1157,9 +1178,189 @@ describe('CredentialsLogic', () => {
         }
       });
     });
+
+    describe('onApiTokenChange', () => {
+      it('calls a POST API endpoint that creates a new token if the active token does not exist yet', async () => {
+        const createdToken = {
+          name: 'new-key',
+          type: ApiTokenTypes.Admin,
+        };
+        mount({
+          activeApiToken: createdToken,
+        });
+        jest.spyOn(CredentialsLogic.actions, 'onApiTokenCreateSuccess');
+        const promise = Promise.resolve(createdToken);
+        http.post.mockReturnValue(promise);
+
+        CredentialsLogic.actions.onApiTokenChange();
+        expect(http.post).toHaveBeenCalledWith('/api/app_search/credentials', {
+          body: JSON.stringify(createdToken),
+        });
+        await promise;
+        expect(CredentialsLogic.actions.onApiTokenCreateSuccess).toHaveBeenCalledWith(createdToken);
+        expect(setSuccessMessage).toHaveBeenCalled();
+      });
+
+      it('calls a PUT endpoint that updates the active token if it already exists', async () => {
+        const updatedToken = {
+          name: 'test-key',
+          type: ApiTokenTypes.Private,
+          read: true,
+          write: false,
+          access_all_engines: false,
+          engines: ['engine1'],
+        };
+        mount({
+          activeApiToken: {
+            ...updatedToken,
+            id: 'some-id',
+          },
+        });
+        jest.spyOn(CredentialsLogic.actions, 'onApiTokenUpdateSuccess');
+        const promise = Promise.resolve(updatedToken);
+        http.put.mockReturnValue(promise);
+
+        CredentialsLogic.actions.onApiTokenChange();
+        expect(http.put).toHaveBeenCalledWith('/api/app_search/credentials/test-key', {
+          body: JSON.stringify(updatedToken),
+        });
+        await promise;
+        expect(CredentialsLogic.actions.onApiTokenUpdateSuccess).toHaveBeenCalledWith(updatedToken);
+        expect(setSuccessMessage).toHaveBeenCalled();
+      });
+
+      it('handles errors', async () => {
+        mount();
+        const promise = Promise.reject('An error occured');
+        http.post.mockReturnValue(promise);
+
+        CredentialsLogic.actions.onApiTokenChange();
+        try {
+          await promise;
+        } catch {
+          expect(flashAPIErrors).toHaveBeenCalledWith('An error occured');
+        }
+      });
+
+      describe('token type data', () => {
+        it('does not send extra read/write/engine access data for admin tokens', () => {
+          const correctAdminToken = {
+            name: 'bogus-admin',
+            type: ApiTokenTypes.Admin,
+          };
+          const extraData = {
+            read: true,
+            write: true,
+            access_all_engines: true,
+          };
+          mount({ activeApiToken: { ...correctAdminToken, ...extraData } });
+
+          CredentialsLogic.actions.onApiTokenChange();
+          expect(http.post).toHaveBeenCalledWith('/api/app_search/credentials', {
+            body: JSON.stringify(correctAdminToken),
+          });
+        });
+
+        it('does not send extra read/write access data for search tokens', () => {
+          const correctSearchToken = {
+            name: 'bogus-search',
+            type: ApiTokenTypes.Search,
+            access_all_engines: false,
+            engines: ['some-engine'],
+          };
+          const extraData = {
+            read: true,
+            write: false,
+          };
+          mount({ activeApiToken: { ...correctSearchToken, ...extraData } });
+
+          CredentialsLogic.actions.onApiTokenChange();
+          expect(http.post).toHaveBeenCalledWith('/api/app_search/credentials', {
+            body: JSON.stringify(correctSearchToken),
+          });
+        });
+
+        // Private tokens send all data per the PUT test above.
+        // If that ever changes, we should capture that in another test here.
+      });
+    });
+
+    describe('onEngineSelect', () => {
+      it('calls addEngineName if the engine is not selected', () => {
+        mount({
+          activeApiToken: {
+            ...DEFAULT_VALUES.activeApiToken,
+            engines: [],
+          },
+        });
+        jest.spyOn(CredentialsLogic.actions, 'addEngineName');
+
+        CredentialsLogic.actions.onEngineSelect('engine1');
+        expect(CredentialsLogic.actions.addEngineName).toHaveBeenCalledWith('engine1');
+        expect(CredentialsLogic.values.activeApiToken.engines).toEqual(['engine1']);
+      });
+
+      it('calls removeEngineName if the engine is already selected', () => {
+        mount({
+          activeApiToken: {
+            ...DEFAULT_VALUES.activeApiToken,
+            engines: ['engine1', 'engine2'],
+          },
+        });
+        jest.spyOn(CredentialsLogic.actions, 'removeEngineName');
+
+        CredentialsLogic.actions.onEngineSelect('engine1');
+        expect(CredentialsLogic.actions.removeEngineName).toHaveBeenCalledWith('engine1');
+        expect(CredentialsLogic.values.activeApiToken.engines).toEqual(['engine2']);
+      });
+    });
   });
 
   describe('selectors', () => {
+    describe('fullEngineAccessChecked', () => {
+      it('should be true if active token is set to access all engines and the user can access all engines', () => {
+        (AppLogic.selectors.myRole as jest.Mock).mockReturnValueOnce({
+          canAccessAllEngines: true,
+        });
+        mount({
+          activeApiToken: {
+            ...DEFAULT_VALUES.activeApiToken,
+            access_all_engines: true,
+          },
+        });
+
+        expect(CredentialsLogic.values.fullEngineAccessChecked).toEqual(true);
+      });
+
+      it('should be false if the token is not set to access all engines', () => {
+        (AppLogic.selectors.myRole as jest.Mock).mockReturnValueOnce({
+          canAccessAllEngines: true,
+        });
+        mount({
+          activeApiToken: {
+            ...DEFAULT_VALUES.activeApiToken,
+            access_all_engines: false,
+          },
+        });
+
+        expect(CredentialsLogic.values.fullEngineAccessChecked).toEqual(false);
+      });
+
+      it('should be false if the user cannot acess all engines', () => {
+        (AppLogic.selectors.myRole as jest.Mock).mockReturnValueOnce({
+          canAccessAllEngines: false,
+        });
+        mount({
+          activeApiToken: {
+            ...DEFAULT_VALUES.activeApiToken,
+            access_all_engines: true,
+          },
+        });
+
+        expect(CredentialsLogic.values.fullEngineAccessChecked).toEqual(false);
+      });
+    });
+
     describe('activeApiTokenExists', () => {
       it('should be false if the token has no id', () => {
         mount({
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts
index c6f929c45eb23..7b8b864b3a317 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts
@@ -7,15 +7,21 @@
 import { kea, MakeLogicType } from 'kea';
 
 import { formatApiName } from '../../utils/format_api_name';
-import { ApiTokenTypes } from './constants';
+import { ApiTokenTypes, CREATE_MESSAGE, UPDATE_MESSAGE, DELETE_MESSAGE } from './constants';
 
 import { HttpLogic } from '../../../shared/http';
+import {
+  FlashMessagesLogic,
+  setSuccessMessage,
+  flashAPIErrors,
+} from '../../../shared/flash_messages';
+import { AppLogic } from '../../app_logic';
+
 import { IMeta } from '../../../../../common/types';
-import { flashAPIErrors } from '../../../shared/flash_messages';
 import { IEngine } from '../../types';
 import { IApiToken, ICredentialsDetails, ITokenReadWrite } from './types';
 
-const defaultApiToken: IApiToken = {
+export const defaultApiToken: IApiToken = {
   name: '',
   type: ApiTokenTypes.Private,
   read: true,
@@ -23,9 +29,7 @@ const defaultApiToken: IApiToken = {
   access_all_engines: true,
 };
 
-// TODO CREATE_MESSAGE, UPDATE_MESSAGE, and DELETE_MESSAGE from ent-search
-
-export interface ICredentialsLogicActions {
+interface ICredentialsLogicActions {
   addEngineName(engineName: string): string;
   onApiKeyDelete(tokenName: string): string;
   onApiTokenCreateSuccess(apiToken: IApiToken): IApiToken;
@@ -46,9 +50,11 @@ export interface ICredentialsLogicActions {
   fetchCredentials(page?: number): number;
   fetchDetails(): { value: boolean };
   deleteApiKey(tokenName: string): string;
+  onApiTokenChange(): void;
+  onEngineSelect(engineName: string): string;
 }
 
-export interface ICredentialsLogicValues {
+interface ICredentialsLogicValues {
   activeApiToken: IApiToken;
   activeApiTokenExists: boolean;
   activeApiTokenRawName: string;
@@ -79,10 +85,7 @@ export const CredentialsLogic = kea<
     setCredentialsData: (meta, apiTokens) => ({ meta, apiTokens }),
     setCredentialsDetails: (details) => details,
     setNameInputBlurred: (nameInputBlurred) => nameInputBlurred,
-    setTokenReadWrite: ({ name, checked }) => ({
-      name,
-      checked,
-    }),
+    setTokenReadWrite: ({ name, checked }) => ({ name, checked }),
     setTokenName: (name) => name,
     setTokenType: (tokenType) => tokenType,
     showCredentialsForm: (apiToken = { ...defaultApiToken }) => apiToken,
@@ -92,6 +95,8 @@ export const CredentialsLogic = kea<
     fetchCredentials: (page) => page,
     fetchDetails: true,
     deleteApiKey: (tokenName) => tokenName,
+    onApiTokenChange: () => null,
+    onEngineSelect: (engineName) => engineName,
   }),
   reducers: () => ({
     apiTokens: [
@@ -204,7 +209,11 @@ export const CredentialsLogic = kea<
     ],
   }),
   selectors: ({ selectors }) => ({
-    // TODO fullEngineAccessChecked from ent-search
+    fullEngineAccessChecked: [
+      () => [AppLogic.selectors.myRole, selectors.activeApiToken],
+      (myRole, activeApiToken) =>
+        !!(myRole.canAccessAllEngines && activeApiToken.access_all_engines),
+    ],
     dataLoading: [
       () => [selectors.isCredentialsDetailsComplete, selectors.isCredentialsDataComplete],
       (isCredentialsDetailsComplete, isCredentialsDataComplete) => {
@@ -217,6 +226,9 @@ export const CredentialsLogic = kea<
     ],
   }),
   listeners: ({ actions, values }) => ({
+    showCredentialsForm: () => {
+      FlashMessagesLogic.actions.clearFlashMessages();
+    },
     initializeCredentialsData: () => {
       actions.fetchCredentials();
       actions.fetchDetails();
@@ -247,11 +259,50 @@ export const CredentialsLogic = kea<
         await http.delete(`/api/app_search/credentials/${tokenName}`);
 
         actions.onApiKeyDelete(tokenName);
+        setSuccessMessage(DELETE_MESSAGE);
       } catch (e) {
         flashAPIErrors(e);
       }
     },
-    // TODO onApiTokenChange from ent-search
-    // TODO onEngineSelect from ent-search
+    onApiTokenChange: async () => {
+      const { id, name, engines, type, read, write } = values.activeApiToken;
+
+      const data: IApiToken = {
+        name,
+        type,
+      };
+      if (type === ApiTokenTypes.Private) {
+        data.read = read;
+        data.write = write;
+      }
+      if (type !== ApiTokenTypes.Admin) {
+        data.access_all_engines = values.fullEngineAccessChecked;
+        data.engines = engines;
+      }
+
+      try {
+        const { http } = HttpLogic.values;
+        const body = JSON.stringify(data);
+
+        if (id) {
+          const response = await http.put(`/api/app_search/credentials/${name}`, { body });
+          actions.onApiTokenUpdateSuccess(response);
+          setSuccessMessage(UPDATE_MESSAGE);
+        } else {
+          const response = await http.post('/api/app_search/credentials', { body });
+          actions.onApiTokenCreateSuccess(response);
+          setSuccessMessage(CREATE_MESSAGE);
+        }
+      } catch (e) {
+        flashAPIErrors(e);
+      }
+    },
+    onEngineSelect: (engineName: string) => {
+      if (values.activeApiToken?.engines?.includes(engineName)) {
+        actions.removeEngineName(engineName);
+      } else {
+        actions.addEngineName(engineName);
+      }
+    },
   }),
 });
diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.test.tsx
index f1f16d1a6f7a4..f2bdc1a8c75b5 100644
--- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.test.tsx
@@ -4,28 +4,30 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-import '../../../__mocks__/kea.mock';
+import { setMockValues } from '../../../__mocks__/kea.mock';
 
 import React from 'react';
-import { useValues } from 'kea';
 import { shallow } from 'enzyme';
 import { EuiPage } from '@elastic/eui';
 
-import { ProductSelector } from './';
+import { SetupGuideCta } from '../setup_guide';
 import { ProductCard } from '../product_card';
 
+import { ProductSelector } from './';
+
 describe('ProductSelector', () => {
-  it('renders the overview page and product cards with no host set', () => {
-    (useValues as jest.Mock).mockImplementationOnce(() => ({ config: { host: '' } }));
+  it('renders the overview page, product cards, & setup guide CTAs with no host set', () => {
+    setMockValues({ config: { host: '' } });
     const wrapper = shallow(<ProductSelector access={{}} />);
 
     expect(wrapper.find(EuiPage).hasClass('enterpriseSearchOverview')).toBe(true);
     expect(wrapper.find(ProductCard)).toHaveLength(2);
+    expect(wrapper.find(SetupGuideCta)).toHaveLength(1);
   });
 
   describe('access checks when host is set', () => {
     beforeEach(() => {
-      (useValues as jest.Mock).mockImplementationOnce(() => ({ config: { host: 'localhost' } }));
+      setMockValues({ config: { host: 'localhost' } });
     });
 
     it('does not render the App Search card if the user does not have access to AS', () => {
diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.tsx
index 6d76b741d7a97..235ececd8b6fc 100644
--- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_selector/product_selector.tsx
@@ -3,11 +3,6 @@
  * or more contributor license agreements. Licensed under the Elastic License;
  * you may not use this file except in compliance with the Elastic License.
  */
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
 
 import React from 'react';
 import { useValues } from 'kea';
@@ -30,6 +25,7 @@ import { SetEnterpriseSearchChrome as SetPageChrome } from '../../../shared/kiba
 import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry';
 
 import { ProductCard } from '../product_card';
+import { SetupGuideCta } from '../setup_guide';
 
 import AppSearchImage from '../../assets/app_search.png';
 import WorkplaceSearchImage from '../../assets/workplace_search.png';
@@ -66,9 +62,13 @@ export const ProductSelector: React.FC<IProductSelectorProps> = ({ access }) =>
             </EuiTitle>
             <EuiTitle size="s">
               <p className="enterpriseSearchOverview__subheading">
-                {i18n.translate('xpack.enterpriseSearch.overview.subheading', {
-                  defaultMessage: 'Select a product to get started',
-                })}
+                {config.host
+                  ? i18n.translate('xpack.enterpriseSearch.overview.subheading', {
+                      defaultMessage: 'Select a product to get started.',
+                    })
+                  : i18n.translate('xpack.enterpriseSearch.overview.setupHeading', {
+                      defaultMessage: 'Choose a product to set up and get started.',
+                    })}
               </p>
             </EuiTitle>
           </EuiPageHeaderSection>
@@ -87,6 +87,7 @@ export const ProductSelector: React.FC<IProductSelectorProps> = ({ access }) =>
             )}
           </EuiFlexGroup>
           <EuiSpacer />
+          {!config.host && <SetupGuideCta />}
         </EuiPageContentBody>
       </EuiPageBody>
     </EuiPage>
diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/index.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/index.ts
index c367424d375f9..89f7da4547569 100644
--- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/index.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/index.ts
@@ -5,3 +5,4 @@
  */
 
 export { SetupGuide } from './setup_guide';
+export { SetupGuideCta } from './setup_guide_cta';
diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.scss b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.scss
new file mode 100644
index 0000000000000..103ef8eccb558
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.scss
@@ -0,0 +1,29 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+.enterpriseSearchSetupCta {
+  margin: $euiSize auto $euiSizeXL;
+
+  // Clickable EuiPanel override - line panel up with product cards
+  &.euiPanel--isClickable {
+    width: calc(100% - #{$euiSize});
+  }
+
+  &__text {
+    max-width: $euiSize * 40;
+  }
+
+  &__image {
+    display: block;
+    max-width: 100%;
+    width: $euiSize * 10;
+    margin: 0 auto;
+
+    @include euiBreakpoint('xs', 's') {
+      width: $euiSize * 15;
+    }
+  }
+}
diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.test.tsx
new file mode 100644
index 0000000000000..f235beef3b337
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.test.tsx
@@ -0,0 +1,19 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { shallow } from 'enzyme';
+
+import { SetupGuideCta } from './';
+
+describe('SetupGuideCta', () => {
+  it('renders', () => {
+    const wrapper = shallow(<SetupGuideCta />);
+
+    expect(wrapper.find('.enterpriseSearchSetupCta')).toHaveLength(1);
+    expect(wrapper.find('img')).toHaveLength(1);
+  });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.tsx
new file mode 100644
index 0000000000000..2a0e2ffc34f3f
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/setup_guide/setup_guide_cta.tsx
@@ -0,0 +1,38 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiText } from '@elastic/eui';
+import { EuiPanel } from '../../../shared/react_router_helpers';
+
+import CtaImage from './assets/getting_started.png';
+import './setup_guide_cta.scss';
+
+export const SetupGuideCta: React.FC = () => (
+  <EuiPanel to="/setup_guide" paddingSize="l" className="enterpriseSearchSetupCta">
+    <EuiFlexGroup alignItems="center" justifyContent="spaceBetween">
+      <EuiFlexItem className="enterpriseSearchSetupCta__text">
+        <EuiTitle size="s">
+          <h2>
+            {i18n.translate('xpack.enterpriseSearch.overview.setupCta.title', {
+              defaultMessage: 'Enterprise-grade functionality for teams big and small',
+            })}
+          </h2>
+        </EuiTitle>
+        <EuiText size="s" color="subdued">
+          {i18n.translate('xpack.enterpriseSearch.overview.setupCta.description', {
+            defaultMessage:
+              'Add search to your app or internal organization with Elastic App Search and Workplace Search. Watch the video to see what you can do when search is made easy.',
+          })}
+        </EuiText>
+      </EuiFlexItem>
+      <EuiFlexItem grow={false}>
+        <img src={CtaImage} alt="" className="enterpriseSearchSetupCta__image" />
+      </EuiFlexItem>
+    </EuiFlexGroup>
+  </EuiPanel>
+);
diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx
index 803d2c8462b1b..0e929c9191e0f 100644
--- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx
@@ -6,10 +6,8 @@
 
 import React from 'react';
 import { shallow } from 'enzyme';
-import { EuiPage } from '@elastic/eui';
 
-import '../__mocks__/kea.mock';
-import { useValues } from 'kea';
+import { setMockValues } from '../__mocks__/kea.mock';
 
 import { EnterpriseSearch } from './';
 import { SetupGuide } from './components/setup_guide';
@@ -18,7 +16,7 @@ import { ProductSelector } from './components/product_selector';
 
 describe('EnterpriseSearch', () => {
   it('renders the Setup Guide and Product Selector', () => {
-    (useValues as jest.Mock).mockReturnValue({
+    setMockValues({
       errorConnecting: false,
       config: { host: 'localhost' },
     });
@@ -28,15 +26,23 @@ describe('EnterpriseSearch', () => {
     expect(wrapper.find(ProductSelector)).toHaveLength(1);
   });
 
-  it('renders the error connecting prompt when host is not configured', () => {
-    (useValues as jest.Mock).mockReturnValueOnce({
+  it('renders the error connecting prompt only if host is configured', () => {
+    setMockValues({
       errorConnecting: true,
-      config: { host: '' },
+      config: { host: 'localhost' },
     });
     const wrapper = shallow(<EnterpriseSearch />);
 
     expect(wrapper.find(ErrorConnecting)).toHaveLength(1);
-    expect(wrapper.find(EuiPage)).toHaveLength(0);
     expect(wrapper.find(ProductSelector)).toHaveLength(0);
+
+    setMockValues({
+      errorConnecting: true,
+      config: { host: '' },
+    });
+    wrapper.setProps({}); // Re-render
+
+    expect(wrapper.find(ErrorConnecting)).toHaveLength(0);
+    expect(wrapper.find(ProductSelector)).toHaveLength(1);
   });
 });
diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx
index 7b97c6c9e58b6..048baabe6a1dd 100644
--- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.tsx
@@ -25,7 +25,7 @@ export const EnterpriseSearch: React.FC<IInitialAppData> = ({ access = {} }) =>
   const { errorConnecting } = useValues(HttpLogic);
   const { config } = useValues(KibanaLogic);
 
-  const showErrorConnecting = config.host && errorConnecting;
+  const showErrorConnecting = !!(config.host && errorConnecting);
 
   return (
     <Switch>
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.test.tsx
index 82fbb8940d460..3a4585b6d9a71 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.test.tsx
@@ -8,18 +8,18 @@ import '../../__mocks__/kea.mock';
 
 import React from 'react';
 import { shallow, mount } from 'enzyme';
-import { EuiLink, EuiButton } from '@elastic/eui';
+import { EuiLink, EuiButton, EuiPanel } from '@elastic/eui';
 
 import { mockKibanaValues, mockHistory } from '../../__mocks__';
 
-import { EuiReactRouterLink, EuiReactRouterButton } from './eui_link';
+import { EuiReactRouterLink, EuiReactRouterButton, EuiReactRouterPanel } from './eui_link';
 
 describe('EUI & React Router Component Helpers', () => {
   beforeEach(() => {
     jest.clearAllMocks();
   });
 
-  it('renders', () => {
+  it('renders an EuiLink', () => {
     const wrapper = shallow(<EuiReactRouterLink to="/" />);
 
     expect(wrapper.find(EuiLink)).toHaveLength(1);
@@ -31,6 +31,13 @@ describe('EUI & React Router Component Helpers', () => {
     expect(wrapper.find(EuiButton)).toHaveLength(1);
   });
 
+  it('renders an EuiPanel', () => {
+    const wrapper = shallow(<EuiReactRouterPanel to="/" paddingSize="l" />);
+
+    expect(wrapper.find(EuiPanel)).toHaveLength(1);
+    expect(wrapper.find(EuiPanel).prop('paddingSize')).toEqual('l');
+  });
+
   it('passes down all ...rest props', () => {
     const wrapper = shallow(<EuiReactRouterLink to="/" data-test-subj="foo" external={true} />);
     const link = wrapper.find(EuiLink);
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.tsx
index f9f6ec54e8832..78546911813ec 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.tsx
@@ -6,14 +6,15 @@
 
 import React from 'react';
 import { useValues } from 'kea';
-import { EuiLink, EuiButton, EuiButtonProps, EuiLinkAnchorProps } from '@elastic/eui';
+import { EuiLink, EuiButton, EuiButtonProps, EuiLinkAnchorProps, EuiPanel } from '@elastic/eui';
+import { EuiPanelProps } from '@elastic/eui/src/components/panel/panel';
 
 import { KibanaLogic } from '../kibana';
 import { HttpLogic } from '../http';
 import { letBrowserHandleEvent, createHref } from './';
 
 /**
- * Generates either an EuiLink or EuiButton with a React-Router-ified link
+ * Generates EUI components with React-Router-ified links
  *
  * Based off of EUI's recommendations for handling React Router:
  * https://github.com/elastic/eui/blob/master/wiki/react-router.md#react-router-51
@@ -54,9 +55,11 @@ export const EuiReactRouterHelper: React.FC<IEuiReactRouterProps> = ({
   return React.cloneElement(children as React.ReactElement, reactRouterProps);
 };
 
-type TEuiReactRouterLinkProps = EuiLinkAnchorProps & IEuiReactRouterProps;
-type TEuiReactRouterButtonProps = EuiButtonProps & IEuiReactRouterProps;
+/**
+ * Component helpers
+ */
 
+type TEuiReactRouterLinkProps = EuiLinkAnchorProps & IEuiReactRouterProps;
 export const EuiReactRouterLink: React.FC<TEuiReactRouterLinkProps> = ({
   to,
   onClick,
@@ -68,6 +71,7 @@ export const EuiReactRouterLink: React.FC<TEuiReactRouterLinkProps> = ({
   </EuiReactRouterHelper>
 );
 
+type TEuiReactRouterButtonProps = EuiButtonProps & IEuiReactRouterProps;
 export const EuiReactRouterButton: React.FC<TEuiReactRouterButtonProps> = ({
   to,
   onClick,
@@ -78,3 +82,15 @@ export const EuiReactRouterButton: React.FC<TEuiReactRouterButtonProps> = ({
     <EuiButton {...rest} />
   </EuiReactRouterHelper>
 );
+
+type TEuiReactRouterPanelProps = EuiPanelProps & IEuiReactRouterProps;
+export const EuiReactRouterPanel: React.FC<TEuiReactRouterPanelProps> = ({
+  to,
+  onClick,
+  shouldNotCreateHref,
+  ...rest
+}) => (
+  <EuiReactRouterHelper {...{ to, onClick, shouldNotCreateHref }}>
+    <EuiPanel {...rest} />
+  </EuiReactRouterHelper>
+);
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/index.ts
index 6915d3222c45c..36fb0560d7323 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/index.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/index.ts
@@ -6,5 +6,8 @@
 
 export { letBrowserHandleEvent } from './link_events';
 export { createHref, ICreateHrefOptions } from './create_href';
-export { EuiReactRouterLink as EuiLink } from './eui_link';
-export { EuiReactRouterButton as EuiButton } from './eui_link';
+export {
+  EuiReactRouterLink as EuiLink,
+  EuiReactRouterButton as EuiButton,
+  EuiReactRouterPanel as EuiPanel,
+} from './eui_link';
diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/credentials.test.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/credentials.test.ts
index 6b5f4a05b3aa6..357b49de93412 100644
--- a/x-pack/plugins/enterprise_search/server/routes/app_search/credentials.test.ts
+++ b/x-pack/plugins/enterprise_search/server/routes/app_search/credentials.test.ts
@@ -41,6 +41,115 @@ describe('credentials routes', () => {
     });
   });
 
+  describe('POST /api/app_search/credentials', () => {
+    let mockRouter: MockRouter;
+
+    beforeEach(() => {
+      jest.clearAllMocks();
+      mockRouter = new MockRouter({ method: 'post', payload: 'body' });
+
+      registerCredentialsRoutes({
+        ...mockDependencies,
+        router: mockRouter.router,
+      });
+    });
+
+    it('creates a request handler', () => {
+      expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({
+        path: '/as/credentials/collection',
+      });
+    });
+
+    describe('validates', () => {
+      describe('admin keys', () => {
+        it('correctly', () => {
+          const request = {
+            body: {
+              name: 'admin-key',
+              type: 'admin',
+            },
+          };
+          mockRouter.shouldValidate(request);
+        });
+
+        it('throws on unnecessary properties', () => {
+          const request = {
+            body: {
+              name: 'admin-key',
+              type: 'admin',
+              read: true,
+              access_all_engines: true,
+            },
+          };
+          mockRouter.shouldThrow(request);
+        });
+      });
+
+      describe('private keys', () => {
+        it('correctly', () => {
+          const request = {
+            body: {
+              name: 'private-key',
+              type: 'private',
+              read: true,
+              write: false,
+              access_all_engines: false,
+              engines: ['engine1', 'engine2'],
+            },
+          };
+          mockRouter.shouldValidate(request);
+        });
+
+        it('throws on missing keys', () => {
+          const request = {
+            body: {
+              name: 'private-key',
+              type: 'private',
+            },
+          };
+          mockRouter.shouldThrow(request);
+        });
+      });
+
+      describe('search keys', () => {
+        it('correctly', () => {
+          const request = {
+            body: {
+              name: 'search-key',
+              type: 'search',
+              access_all_engines: true,
+            },
+          };
+          mockRouter.shouldValidate(request);
+        });
+
+        it('throws on missing keys', () => {
+          const request = {
+            body: {
+              name: 'search-key',
+              type: 'search',
+            },
+          };
+          mockRouter.shouldThrow(request);
+        });
+
+        it('throws on extra keys', () => {
+          const request = {
+            body: {
+              name: 'search-key',
+              type: 'search',
+              read: true,
+              write: false,
+              access_all_engines: false,
+              engines: ['engine1', 'engine2'],
+            },
+          };
+          mockRouter.shouldThrow(request);
+        });
+      });
+    });
+  });
+
   describe('GET /api/app_search/credentials/details', () => {
     let mockRouter: MockRouter;
 
@@ -61,6 +170,123 @@ describe('credentials routes', () => {
     });
   });
 
+  describe('PUT /api/app_search/credentials/{name}', () => {
+    let mockRouter: MockRouter;
+
+    beforeEach(() => {
+      jest.clearAllMocks();
+      mockRouter = new MockRouter({ method: 'put', payload: 'body' });
+
+      registerCredentialsRoutes({
+        ...mockDependencies,
+        router: mockRouter.router,
+      });
+    });
+
+    it('creates a request to enterprise search', () => {
+      const mockRequest = {
+        params: {
+          name: 'abc123',
+        },
+      };
+
+      mockRouter.callRoute(mockRequest);
+
+      expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({
+        path: '/as/credentials/abc123',
+      });
+    });
+
+    describe('validates', () => {
+      describe('admin keys', () => {
+        it('correctly', () => {
+          const request = {
+            body: {
+              name: 'admin-key',
+              type: 'admin',
+            },
+          };
+          mockRouter.shouldValidate(request);
+        });
+
+        it('throws on unnecessary properties', () => {
+          const request = {
+            body: {
+              name: 'admin-key',
+              type: 'admin',
+              read: true,
+              access_all_engines: true,
+            },
+          };
+          mockRouter.shouldThrow(request);
+        });
+      });
+
+      describe('private keys', () => {
+        it('correctly', () => {
+          const request = {
+            body: {
+              name: 'private-key',
+              type: 'private',
+              read: true,
+              write: false,
+              access_all_engines: false,
+              engines: ['engine1', 'engine2'],
+            },
+          };
+          mockRouter.shouldValidate(request);
+        });
+
+        it('throws on missing keys', () => {
+          const request = {
+            body: {
+              name: 'private-key',
+              type: 'private',
+            },
+          };
+          mockRouter.shouldThrow(request);
+        });
+      });
+
+      describe('search keys', () => {
+        it('correctly', () => {
+          const request = {
+            body: {
+              name: 'search-key',
+              type: 'search',
+              access_all_engines: true,
+            },
+          };
+          mockRouter.shouldValidate(request);
+        });
+
+        it('throws on missing keys', () => {
+          const request = {
+            body: {
+              name: 'search-key',
+              type: 'search',
+            },
+          };
+          mockRouter.shouldThrow(request);
+        });
+
+        it('throws on extra keys', () => {
+          const request = {
+            body: {
+              name: 'search-key',
+              type: 'search',
+              read: true,
+              write: false,
+              access_all_engines: false,
+              engines: ['engine1', 'engine2'],
+            },
+          };
+          mockRouter.shouldThrow(request);
+        });
+      });
+    });
+  });
+
   describe('DELETE /api/app_search/credentials/{name}', () => {
     let mockRouter: MockRouter;
 
diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/credentials.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/credentials.ts
index 0f2c1133192c5..85d213c82dd05 100644
--- a/x-pack/plugins/enterprise_search/server/routes/app_search/credentials.ts
+++ b/x-pack/plugins/enterprise_search/server/routes/app_search/credentials.ts
@@ -8,10 +8,32 @@ import { schema } from '@kbn/config-schema';
 
 import { IRouteDependencies } from '../../plugin';
 
+const tokenSchema = schema.oneOf([
+  schema.object({
+    name: schema.string(),
+    type: schema.literal('admin'),
+  }),
+  schema.object({
+    name: schema.string(),
+    type: schema.literal('private'),
+    read: schema.boolean(),
+    write: schema.boolean(),
+    access_all_engines: schema.boolean(),
+    engines: schema.maybe(schema.arrayOf(schema.string())),
+  }),
+  schema.object({
+    name: schema.string(),
+    type: schema.literal('search'),
+    access_all_engines: schema.boolean(),
+    engines: schema.maybe(schema.arrayOf(schema.string())),
+  }),
+]);
+
 export function registerCredentialsRoutes({
   router,
   enterpriseSearchRequestHandler,
 }: IRouteDependencies) {
+  // Credentials API
   router.get(
     {
       path: '/api/app_search/credentials',
@@ -25,6 +47,19 @@ export function registerCredentialsRoutes({
       path: '/as/credentials/collection',
     })
   );
+  router.post(
+    {
+      path: '/api/app_search/credentials',
+      validate: {
+        body: tokenSchema,
+      },
+    },
+    enterpriseSearchRequestHandler.createRequest({
+      path: '/as/credentials/collection',
+    })
+  );
+
+  // TODO: It would be great to remove this someday
   router.get(
     {
       path: '/api/app_search/credentials/details',
@@ -34,6 +69,24 @@ export function registerCredentialsRoutes({
       path: '/as/credentials/details',
     })
   );
+
+  // Single credential API
+  router.put(
+    {
+      path: '/api/app_search/credentials/{name}',
+      validate: {
+        params: schema.object({
+          name: schema.string(),
+        }),
+        body: tokenSchema,
+      },
+    },
+    async (context, request, response) => {
+      return enterpriseSearchRequestHandler.createRequest({
+        path: `/as/credentials/${request.params.name}`,
+      })(context, request, response);
+    }
+  );
   router.delete(
     {
       path: '/api/app_search/credentials/{name}',
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts
index bd845b0a7d9a7..0a96146339a58 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts
@@ -14,17 +14,52 @@ export const DEFAULT_POLICY: PolicyFromES = {
   version: 1,
   modified_date: Date.now().toString(),
   policy: {
-    name: '',
+    name: 'my_policy',
+    phases: {
+      hot: {
+        min_age: '0ms',
+        actions: {
+          rollover: {
+            max_age: '30d',
+            max_size: '50gb',
+          },
+        },
+      },
+    },
+  },
+  name: 'my_policy',
+};
+
+export const POLICY_WITH_INCLUDE_EXCLUDE: PolicyFromES = {
+  version: 1,
+  modified_date: Date.now().toString(),
+  policy: {
+    name: 'my_policy',
     phases: {
       hot: {
         min_age: '123ms',
         actions: {
-          rollover: {},
+          rollover: {
+            max_age: '30d',
+            max_size: '50gb',
+          },
+        },
+      },
+      warm: {
+        actions: {
+          allocate: {
+            include: {
+              abc: '123',
+            },
+            exclude: {
+              def: '456',
+            },
+          },
         },
       },
     },
   },
-  name: '',
+  name: 'my_policy',
 };
 
 export const DELETE_PHASE_POLICY: PolicyFromES = {
@@ -60,3 +95,58 @@ export const DELETE_PHASE_POLICY: PolicyFromES = {
   },
   name: POLICY_NAME,
 };
+
+export const POLICY_WITH_NODE_ATTR_AND_OFF_ALLOCATION: PolicyFromES = {
+  version: 1,
+  modified_date: Date.now().toString(),
+  policy: {
+    phases: {
+      hot: {
+        min_age: '0ms',
+        actions: {
+          rollover: {
+            max_size: '50gb',
+          },
+        },
+      },
+      warm: {
+        actions: {
+          allocate: {
+            require: {},
+            include: { test: '123' },
+            exclude: {},
+          },
+        },
+      },
+      cold: {
+        actions: {
+          migrate: { enabled: false },
+        },
+      },
+    },
+    name: POLICY_NAME,
+  },
+  name: POLICY_NAME,
+};
+
+export const POLICY_WITH_NODE_ROLE_ALLOCATION: PolicyFromES = {
+  version: 1,
+  modified_date: Date.now().toString(),
+  policy: {
+    phases: {
+      hot: {
+        min_age: '0ms',
+        actions: {
+          rollover: {
+            max_size: '50gb',
+          },
+        },
+      },
+      warm: {
+        actions: {},
+      },
+    },
+    name: POLICY_NAME,
+  },
+  name: POLICY_NAME,
+};
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx
index 0cfccba761309..1716f124b0c83 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx
@@ -9,11 +9,16 @@ import { act } from 'react-dom/test-utils';
 
 import { registerTestBed, TestBedConfig } from '../../../../../test_utils';
 
+import { EditPolicy } from '../../../public/application/sections/edit_policy';
+import { DataTierAllocationType } from '../../../public/application/sections/edit_policy/types';
+
+import { Phases as PolicyPhases } from '../../../common/types';
+
+type Phases = keyof PolicyPhases;
+
 import { POLICY_NAME } from './constants';
 import { TestSubjects } from '../helpers';
 
-import { EditPolicy } from '../../../public/application/sections/edit_policy';
-
 jest.mock('@elastic/eui', () => {
   const original = jest.requireActual('@elastic/eui');
 
@@ -52,7 +57,23 @@ export type EditPolicyTestBed = SetupReturn extends Promise<infer U> ? U : Setup
 export const setup = async () => {
   const testBed = await initTestBed();
 
-  const { find, component } = testBed;
+  const { find, component, form } = testBed;
+
+  const createFormToggleAction = (dataTestSubject: string) => async (checked: boolean) => {
+    await act(async () => {
+      form.toggleEuiSwitch(dataTestSubject, checked);
+    });
+    component.update();
+  };
+
+  function createFormSetValueAction<V extends string = string>(dataTestSubject: string) {
+    return async (value: V) => {
+      await act(async () => {
+        form.setInputValue(dataTestSubject, value);
+      });
+      component.update();
+    };
+  }
 
   const setWaitForSnapshotPolicy = async (snapshotPolicyName: string) => {
     act(() => {
@@ -68,12 +89,7 @@ export const setup = async () => {
     component.update();
   };
 
-  const toggleRollover = async (checked: boolean) => {
-    await act(async () => {
-      find('rolloverSwitch').simulate('click', { target: { checked } });
-    });
-    component.update();
-  };
+  const toggleRollover = createFormToggleAction('rolloverSwitch');
 
   const setMaxSize = async (value: string, units?: string) => {
     await act(async () => {
@@ -87,12 +103,7 @@ export const setup = async () => {
     component.update();
   };
 
-  const setMaxDocs = async (value: string) => {
-    await act(async () => {
-      find('hot-selectedMaxDocuments').simulate('change', { target: { value } });
-    });
-    component.update();
-  };
+  const setMaxDocs = createFormSetValueAction('hot-selectedMaxDocuments');
 
   const setMaxAge = async (value: string, units?: string) => {
     await act(async () => {
@@ -104,32 +115,56 @@ export const setup = async () => {
     component.update();
   };
 
-  const toggleForceMerge = (phase: string) => async (checked: boolean) => {
-    await act(async () => {
-      find(`${phase}-forceMergeSwitch`).simulate('click', { target: { checked } });
+  const toggleForceMerge = (phase: Phases) => createFormToggleAction(`${phase}-forceMergeSwitch`);
+
+  const setForcemergeSegmentsCount = (phase: Phases) =>
+    createFormSetValueAction(`${phase}-selectedForceMergeSegments`);
+
+  const setBestCompression = (phase: Phases) => createFormToggleAction(`${phase}-bestCompression`);
+
+  const setIndexPriority = (phase: Phases) =>
+    createFormSetValueAction(`${phase}-phaseIndexPriority`);
+
+  const enable = (phase: Phases) => createFormToggleAction(`enablePhaseSwitch-${phase}`);
+
+  const warmPhaseOnRollover = createFormToggleAction(`warm-warmPhaseOnRollover`);
+
+  const setMinAgeValue = (phase: Phases) => createFormSetValueAction(`${phase}-selectedMinimumAge`);
+
+  const setMinAgeUnits = (phase: Phases) =>
+    createFormSetValueAction(`${phase}-selectedMinimumAgeUnits`);
+
+  const setDataAllocation = (phase: Phases) => async (value: DataTierAllocationType) => {
+    act(() => {
+      find(`${phase}-dataTierAllocationControls.dataTierSelect`).simulate('click');
     });
     component.update();
-  };
-
-  const setForcemergeSegmentsCount = (phase: string) => async (value: string) => {
     await act(async () => {
-      find(`${phase}-selectedForceMergeSegments`).simulate('change', { target: { value } });
+      switch (value) {
+        case 'node_roles':
+          find(`${phase}-dataTierAllocationControls.defaultDataAllocationOption`).simulate('click');
+          break;
+        case 'node_attrs':
+          find(`${phase}-dataTierAllocationControls.customDataAllocationOption`).simulate('click');
+          break;
+        default:
+          find(`${phase}-dataTierAllocationControls.noneDataAllocationOption`).simulate('click');
+      }
     });
     component.update();
   };
 
-  const setBestCompression = (phase: string) => async (checked: boolean) => {
-    await act(async () => {
-      find(`${phase}-bestCompression`).simulate('click', { target: { checked } });
-    });
-    component.update();
+  const setSelectedNodeAttribute = (phase: string) =>
+    createFormSetValueAction(`${phase}-selectedNodeAttrs`);
+
+  const setReplicas = async (value: string) => {
+    await createFormToggleAction('warm-setReplicasSwitch')(true);
+    await createFormSetValueAction('warm-selectedReplicaCount')(value);
   };
 
-  const setIndexPriority = (phase: string) => async (value: string) => {
-    await act(async () => {
-      find(`${phase}-phaseIndexPriority`).simulate('change', { target: { value } });
-    });
-    component.update();
+  const setShrink = async (value: string) => {
+    await createFormToggleAction('shrinkSwitch')(true);
+    await createFormSetValueAction('warm-selectedPrimaryShardCount')(value);
   };
 
   return {
@@ -147,6 +182,20 @@ export const setup = async () => {
         setBestCompression: setBestCompression('hot'),
         setIndexPriority: setIndexPriority('hot'),
       },
+      warm: {
+        enable: enable('warm'),
+        warmPhaseOnRollover,
+        setMinAgeValue: setMinAgeValue('warm'),
+        setMinAgeUnits: setMinAgeUnits('warm'),
+        setDataAllocation: setDataAllocation('warm'),
+        setSelectedNodeAttribute: setSelectedNodeAttribute('warm'),
+        setReplicas,
+        setShrink,
+        toggleForceMerge: toggleForceMerge('warm'),
+        setForcemergeSegments: setForcemergeSegmentsCount('warm'),
+        setBestCompression: setBestCompression('warm'),
+        setIndexPriority: setIndexPriority('warm'),
+      },
     },
   };
 };
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts
index 3cbc2d982566e..fccffde3f793f 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts
@@ -15,6 +15,9 @@ import {
   NEW_SNAPSHOT_POLICY_NAME,
   SNAPSHOT_POLICY_NAME,
   DEFAULT_POLICY,
+  POLICY_WITH_INCLUDE_EXCLUDE,
+  POLICY_WITH_NODE_ATTR_AND_OFF_ALLOCATION,
+  POLICY_WITH_NODE_ROLE_ALLOCATION,
 } from './constants';
 
 window.scrollTo = jest.fn();
@@ -53,7 +56,8 @@ describe('<EditPolicy />', () => {
 
         await actions.savePolicy();
         const latestRequest = server.requests[server.requests.length - 1];
-        expect(JSON.parse(JSON.parse(latestRequest.requestBody).body)).toMatchInlineSnapshot(`
+        const entirePolicy = JSON.parse(JSON.parse(latestRequest.requestBody).body);
+        expect(entirePolicy).toMatchInlineSnapshot(`
           Object {
             "name": "my_policy",
             "phases": Object {
@@ -81,21 +85,184 @@ describe('<EditPolicy />', () => {
 
       test('disabling rollover', async () => {
         const { actions } = testBed;
-        await actions.hot.toggleRollover(false);
+        await actions.hot.toggleRollover(true);
         await actions.savePolicy();
         const latestRequest = server.requests[server.requests.length - 1];
-        expect(JSON.parse(JSON.parse(latestRequest.requestBody).body)).toMatchInlineSnapshot(`
+        const policy = JSON.parse(JSON.parse(latestRequest.requestBody).body);
+        const hotActions = policy.phases.hot.actions;
+        const rolloverAction = hotActions.rollover;
+        expect(rolloverAction).toBe(undefined);
+        expect(hotActions).toMatchInlineSnapshot(`
+          Object {
+            "set_priority": Object {
+              "priority": 100,
+            },
+          }
+        `);
+      });
+    });
+  });
+
+  describe('warm phase', () => {
+    describe('serialization', () => {
+      beforeEach(async () => {
+        httpRequestsMockHelpers.setLoadPolicies([DEFAULT_POLICY]);
+        httpRequestsMockHelpers.setListNodes({
+          nodesByRoles: {},
+          nodesByAttributes: { test: ['123'] },
+          isUsingDeprecatedDataRoleConfig: false,
+        });
+        httpRequestsMockHelpers.setLoadSnapshotPolicies([]);
+
+        await act(async () => {
+          testBed = await setup();
+        });
+
+        const { component } = testBed;
+        component.update();
+      });
+
+      test('default values', async () => {
+        const { actions } = testBed;
+        await actions.warm.enable(true);
+        await actions.savePolicy();
+        const latestRequest = server.requests[server.requests.length - 1];
+        const warmPhase = JSON.parse(JSON.parse(latestRequest.requestBody).body).phases.warm;
+        expect(warmPhase).toMatchInlineSnapshot(`
+          Object {
+            "actions": Object {
+              "set_priority": Object {
+                "priority": 50,
+              },
+            },
+            "min_age": "0ms",
+          }
+        `);
+      });
+
+      test('setting all values', async () => {
+        const { actions } = testBed;
+        await actions.warm.enable(true);
+        await actions.warm.setMinAgeValue('123');
+        await actions.warm.setMinAgeUnits('d');
+        await actions.warm.setDataAllocation('node_attrs');
+        await actions.warm.setSelectedNodeAttribute('test:123');
+        await actions.warm.setReplicas('123');
+        await actions.warm.setShrink('123');
+        await actions.warm.toggleForceMerge(true);
+        await actions.warm.setForcemergeSegments('123');
+        await actions.warm.setBestCompression(true);
+        await actions.warm.setIndexPriority('123');
+        await actions.savePolicy();
+        const latestRequest = server.requests[server.requests.length - 1];
+        const entirePolicy = JSON.parse(JSON.parse(latestRequest.requestBody).body);
+        // Check shape of entire policy
+        expect(entirePolicy).toMatchInlineSnapshot(`
           Object {
             "name": "my_policy",
             "phases": Object {
               "hot": Object {
                 "actions": Object {
+                  "rollover": Object {
+                    "max_age": "30d",
+                    "max_size": "50gb",
+                  },
                   "set_priority": Object {
                     "priority": 100,
                   },
                 },
                 "min_age": "0ms",
               },
+              "warm": Object {
+                "actions": Object {
+                  "allocate": Object {
+                    "number_of_replicas": 123,
+                    "require": Object {
+                      "test": "123",
+                    },
+                  },
+                  "forcemerge": Object {
+                    "index_codec": "best_compression",
+                    "max_num_segments": 123,
+                  },
+                  "set_priority": Object {
+                    "priority": 123,
+                  },
+                  "shrink": Object {
+                    "number_of_shards": 123,
+                  },
+                },
+                "min_age": "123d",
+              },
+            },
+          }
+        `);
+      });
+
+      test('default allocation with replicas set', async () => {
+        const { actions } = testBed;
+        await actions.warm.enable(true);
+        await actions.warm.setReplicas('123');
+        await actions.savePolicy();
+        const latestRequest = server.requests[server.requests.length - 1];
+        const warmPhaseActions = JSON.parse(JSON.parse(latestRequest.requestBody).body).phases.warm
+          .actions;
+        expect(warmPhaseActions).toMatchInlineSnapshot(`
+          Object {
+            "allocate": Object {
+              "number_of_replicas": 123,
+            },
+            "set_priority": Object {
+              "priority": 50,
+            },
+          }
+        `);
+      });
+
+      test('setting warm phase on rollover to "true"', async () => {
+        const { actions } = testBed;
+        await actions.warm.enable(true);
+        await actions.warm.warmPhaseOnRollover(true);
+        await actions.savePolicy();
+        const latestRequest = server.requests[server.requests.length - 1];
+        const warmPhaseMinAge = JSON.parse(JSON.parse(latestRequest.requestBody).body).phases.warm
+          .min_age;
+        expect(warmPhaseMinAge).toBe(undefined);
+      });
+    });
+
+    describe('policy with include and exclude', () => {
+      beforeEach(async () => {
+        httpRequestsMockHelpers.setLoadPolicies([POLICY_WITH_INCLUDE_EXCLUDE]);
+        httpRequestsMockHelpers.setListNodes({
+          nodesByRoles: {},
+          nodesByAttributes: { test: ['123'] },
+          isUsingDeprecatedDataRoleConfig: false,
+        });
+        httpRequestsMockHelpers.setLoadSnapshotPolicies([]);
+
+        await act(async () => {
+          testBed = await setup();
+        });
+
+        const { component } = testBed;
+        component.update();
+      });
+
+      test('preserves include, exclude allocation settings', async () => {
+        const { actions } = testBed;
+        await actions.warm.setDataAllocation('node_attrs');
+        await actions.savePolicy();
+        const latestRequest = server.requests[server.requests.length - 1];
+        const warmPhaseAllocate = JSON.parse(JSON.parse(latestRequest.requestBody).body).phases.warm
+          .actions.allocate;
+        expect(warmPhaseAllocate).toMatchInlineSnapshot(`
+          Object {
+            "exclude": Object {
+              "def": "456",
+            },
+            "include": Object {
+              "abc": "123",
             },
           }
         `);
@@ -216,4 +383,57 @@ describe('<EditPolicy />', () => {
       expect(testBed.find('policiesErrorCallout').exists()).toBeTruthy();
     });
   });
+
+  describe('data allocation', () => {
+    describe('node roles', () => {
+      beforeEach(async () => {
+        httpRequestsMockHelpers.setLoadPolicies([POLICY_WITH_NODE_ROLE_ALLOCATION]);
+        httpRequestsMockHelpers.setListNodes({
+          isUsingDeprecatedDataRoleConfig: false,
+          nodesByAttributes: { test: ['123'] },
+          nodesByRoles: { data: ['123'] },
+        });
+
+        await act(async () => {
+          testBed = await setup();
+        });
+
+        const { component } = testBed;
+        component.update();
+      });
+      test('showing "default" type', () => {
+        const { find } = testBed;
+        expect(find('warm-dataTierAllocationControls.dataTierSelect').text()).toContain(
+          'recommended'
+        );
+        expect(find('warm-dataTierAllocationControls.dataTierSelect').text()).not.toContain(
+          'Custom'
+        );
+        expect(find('warm-dataTierAllocationControls.dataTierSelect').text()).not.toContain('Off');
+      });
+    });
+    describe('node attr and none', () => {
+      beforeEach(async () => {
+        httpRequestsMockHelpers.setLoadPolicies([POLICY_WITH_NODE_ATTR_AND_OFF_ALLOCATION]);
+        httpRequestsMockHelpers.setListNodes({
+          isUsingDeprecatedDataRoleConfig: false,
+          nodesByAttributes: { test: ['123'] },
+          nodesByRoles: { data: ['123'] },
+        });
+
+        await act(async () => {
+          testBed = await setup();
+        });
+
+        const { component } = testBed;
+        component.update();
+      });
+
+      test('showing "custom" and "off" types', () => {
+        const { find } = testBed;
+        expect(find('warm-dataTierAllocationControls.dataTierSelect').text()).toContain('Custom');
+        expect(find('cold-dataTierAllocationControls.dataTierSelect').text()).toContain('Off');
+      });
+    });
+  });
 });
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/http_requests.ts
index 04f58f93939ca..c7a493ce80d96 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/http_requests.ts
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/http_requests.ts
@@ -6,6 +6,7 @@
 
 import { fakeServer, SinonFakeServer } from 'sinon';
 import { API_BASE_PATH } from '../../../common/constants';
+import { ListNodesRouteResponse } from '../../../common/types';
 
 export const init = () => {
   const server = fakeServer.create();
@@ -38,8 +39,17 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => {
     ]);
   };
 
+  const setListNodes = (body: ListNodesRouteResponse) => {
+    server.respondWith('GET', `${API_BASE_PATH}/nodes/list`, [
+      200,
+      { 'Content-Type': 'application/json' },
+      JSON.stringify(body),
+    ]);
+  };
+
   return {
     setLoadPolicies,
     setLoadSnapshotPolicies,
+    setListNodes,
   };
 };
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx
index c7664f2d837b9..4ba6cee7b027f 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx
@@ -30,9 +30,7 @@ import { init as initUiMetric } from '../../public/application/services/ui_metri
 import { init as initNotification } from '../../public/application/services/notification';
 import { PolicyFromES } from '../../common/types';
 import {
-  positiveNumbersAboveZeroErrorMessage,
   positiveNumberRequiredMessage,
-  numberRequiredMessage,
   policyNameRequiredMessage,
   policyNameStartsWithUnderscoreErrorMessage,
   policyNameContainsCommaErrorMessage,
@@ -40,6 +38,8 @@ import {
   policyNameMustBeDifferentErrorMessage,
   policyNameAlreadyUsedErrorMessage,
 } from '../../public/application/services/policies/policy_validation';
+
+import { i18nTexts } from '../../public/application/sections/edit_policy/i18n_texts';
 import { editPolicyHelpers } from './helpers';
 
 // @ts-ignore
@@ -89,13 +89,13 @@ const activatePhase = async (rendered: ReactWrapper, phase: string) => {
   });
   rendered.update();
 };
-const openNodeAttributesSection = (rendered: ReactWrapper, phase: string) => {
+const openNodeAttributesSection = async (rendered: ReactWrapper, phase: string) => {
   const getControls = () => findTestSubject(rendered, `${phase}-dataTierAllocationControls`);
-  act(() => {
+  await act(async () => {
     findTestSubject(getControls(), 'dataTierSelect').simulate('click');
   });
   rendered.update();
-  act(() => {
+  await act(async () => {
     findTestSubject(getControls(), 'customDataAllocationOption').simulate('click');
   });
   rendered.update();
@@ -119,19 +119,29 @@ const noRollover = async (rendered: ReactWrapper) => {
   });
   rendered.update();
 };
-const getNodeAttributeSelect = (rendered: ReactWrapper, phase: string) => {
+const getNodeAttributeSelectLegacy = (rendered: ReactWrapper, phase: string) => {
   return rendered.find(`select#${phase}-selectedNodeAttrs`);
 };
+const getNodeAttributeSelect = (rendered: ReactWrapper, phase: string) => {
+  return findTestSubject(rendered, `${phase}-selectedNodeAttrs`);
+};
 const setPolicyName = (rendered: ReactWrapper, policyName: string) => {
   const policyNameField = findTestSubject(rendered, 'policyNameField');
   policyNameField.simulate('change', { target: { value: policyName } });
   rendered.update();
 };
-const setPhaseAfter = (rendered: ReactWrapper, phase: string, after: string | number) => {
+const setPhaseAfterLegacy = (rendered: ReactWrapper, phase: string, after: string | number) => {
   const afterInput = rendered.find(`input#${phase}-selectedMinimumAge`);
   afterInput.simulate('change', { target: { value: after } });
   rendered.update();
 };
+const setPhaseAfter = async (rendered: ReactWrapper, phase: string, after: string | number) => {
+  const afterInput = findTestSubject(rendered, `${phase}-selectedMinimumAge`);
+  await act(async () => {
+    afterInput.simulate('change', { target: { value: after } });
+  });
+  rendered.update();
+};
 const setPhaseIndexPriorityLegacy = (
   rendered: ReactWrapper,
   phase: string,
@@ -172,10 +182,11 @@ describe('edit policy', () => {
    * any validation errors. This helper advances timers and can trigger component
    * state changes.
    */
-  const waitForFormLibValidation = () => {
+  const waitForFormLibValidation = (rendered: ReactWrapper) => {
     act(() => {
       jest.advanceTimersByTime(1000);
     });
+    rendered.update();
   };
 
   beforeEach(() => {
@@ -288,13 +299,12 @@ describe('edit policy', () => {
       await act(async () => {
         maxSizeInput.simulate('change', { target: { value: '' } });
       });
-      waitForFormLibValidation();
+      waitForFormLibValidation(rendered);
       const maxAgeInput = findTestSubject(rendered, 'hot-selectedMaxAge');
       await act(async () => {
         maxAgeInput.simulate('change', { target: { value: '' } });
       });
-      waitForFormLibValidation();
-      rendered.update();
+      waitForFormLibValidation(rendered);
       await save(rendered);
       expect(findTestSubject(rendered, 'rolloverSettingsRequired').exists()).toBeTruthy();
     });
@@ -305,9 +315,9 @@ describe('edit policy', () => {
       await act(async () => {
         maxSizeInput.simulate('change', { target: { value: '-1' } });
       });
-      waitForFormLibValidation();
+      waitForFormLibValidation(rendered);
       rendered.update();
-      expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]);
+      expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]);
     });
     test('should show number above 0 required error when trying to save with 0 for max size', async () => {
       const rendered = mountWithIntl(component);
@@ -316,9 +326,8 @@ describe('edit policy', () => {
       await act(async () => {
         maxSizeInput.simulate('change', { target: { value: '-1' } });
       });
-      waitForFormLibValidation();
-      rendered.update();
-      expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]);
+      waitForFormLibValidation(rendered);
+      expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]);
     });
     test('should show number above 0 required error when trying to save with -1 for max age', async () => {
       const rendered = mountWithIntl(component);
@@ -327,9 +336,8 @@ describe('edit policy', () => {
       await act(async () => {
         maxAgeInput.simulate('change', { target: { value: '-1' } });
       });
-      waitForFormLibValidation();
-      rendered.update();
-      expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]);
+      waitForFormLibValidation(rendered);
+      expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]);
     });
     test('should show number above 0 required error when trying to save with 0 for max age', async () => {
       const rendered = mountWithIntl(component);
@@ -338,9 +346,8 @@ describe('edit policy', () => {
       await act(async () => {
         maxAgeInput.simulate('change', { target: { value: '0' } });
       });
-      waitForFormLibValidation();
-      rendered.update();
-      expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]);
+      waitForFormLibValidation(rendered);
+      expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]);
     });
     test('should show forcemerge input when rollover enabled', () => {
       const rendered = mountWithIntl(component);
@@ -351,8 +358,7 @@ describe('edit policy', () => {
       const rendered = mountWithIntl(component);
       setPolicyName(rendered, 'mypolicy');
       await noRollover(rendered);
-      waitForFormLibValidation();
-      rendered.update();
+      waitForFormLibValidation(rendered);
       expect(findTestSubject(rendered, 'hot-forceMergeSwitch').exists()).toBeFalsy();
     });
     test('should show positive number required above zero error when trying to save hot phase with 0 for force merge', async () => {
@@ -366,9 +372,8 @@ describe('edit policy', () => {
       await act(async () => {
         forcemergeInput.simulate('change', { target: { value: '0' } });
       });
-      waitForFormLibValidation();
-      rendered.update();
-      expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]);
+      waitForFormLibValidation(rendered);
+      expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]);
     });
     test('should show positive number above 0 required error when trying to save hot phase with -1 for force merge', async () => {
       const rendered = mountWithIntl(component);
@@ -379,19 +384,17 @@ describe('edit policy', () => {
       await act(async () => {
         forcemergeInput.simulate('change', { target: { value: '-1' } });
       });
-      waitForFormLibValidation();
-      rendered.update();
+      waitForFormLibValidation(rendered);
       await save(rendered);
-      expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]);
+      expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]);
     });
     test('should show positive number required error when trying to save with -1 for index priority', async () => {
       const rendered = mountWithIntl(component);
       await noRollover(rendered);
       setPolicyName(rendered, 'mypolicy');
       await setPhaseIndexPriority(rendered, 'hot', '-1');
-      waitForFormLibValidation();
-      rendered.update();
-      expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]);
+      waitForFormLibValidation(rendered);
+      expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]);
     });
   });
   describe('warm phase', () => {
@@ -408,17 +411,17 @@ describe('edit policy', () => {
       await noRollover(rendered);
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'warm');
-      setPhaseAfter(rendered, 'warm', '');
-      await save(rendered);
-      expectedErrorMessages(rendered, [numberRequiredMessage]);
+      await setPhaseAfter(rendered, 'warm', '');
+      waitForFormLibValidation(rendered);
+      expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]);
     });
     test('should allow 0 for phase timing', async () => {
       const rendered = mountWithIntl(component);
       await noRollover(rendered);
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'warm');
-      setPhaseAfter(rendered, 'warm', '0');
-      await save(rendered);
+      await setPhaseAfter(rendered, 'warm', '0');
+      waitForFormLibValidation(rendered);
       expectedErrorMessages(rendered, []);
     });
     test('should show positive number required error when trying to save warm phase with -1 for after', async () => {
@@ -426,75 +429,87 @@ describe('edit policy', () => {
       await noRollover(rendered);
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'warm');
-      setPhaseAfter(rendered, 'warm', '-1');
-      await save(rendered);
-      expectedErrorMessages(rendered, [positiveNumberRequiredMessage]);
+      await setPhaseAfter(rendered, 'warm', '-1');
+      waitForFormLibValidation(rendered);
+      expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]);
     });
     test('should show positive number required error when trying to save warm phase with -1 for index priority', async () => {
       const rendered = mountWithIntl(component);
       await noRollover(rendered);
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'warm');
-      setPhaseAfter(rendered, 'warm', '1');
-      setPhaseIndexPriorityLegacy(rendered, 'warm', '-1');
-      await save(rendered);
-      expectedErrorMessages(rendered, [positiveNumberRequiredMessage]);
+      await setPhaseAfter(rendered, 'warm', '1');
+      await setPhaseAfter(rendered, 'warm', '-1');
+      waitForFormLibValidation(rendered);
+      expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]);
     });
     test('should show positive number required above zero error when trying to save warm phase with 0 for shrink', async () => {
       const rendered = mountWithIntl(component);
       await noRollover(rendered);
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'warm');
-      findTestSubject(rendered, 'shrinkSwitch').simulate('click');
-      rendered.update();
-      setPhaseAfter(rendered, 'warm', '1');
-      const shrinkInput = rendered.find('input#warm-selectedPrimaryShardCount');
-      shrinkInput.simulate('change', { target: { value: '0' } });
+      act(() => {
+        findTestSubject(rendered, 'shrinkSwitch').simulate('click');
+      });
       rendered.update();
-      await save(rendered);
-      expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]);
+      await setPhaseAfter(rendered, 'warm', '1');
+      const shrinkInput = findTestSubject(rendered, 'warm-selectedPrimaryShardCount');
+      await act(async () => {
+        shrinkInput.simulate('change', { target: { value: '0' } });
+      });
+      waitForFormLibValidation(rendered);
+      expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]);
     });
     test('should show positive number above 0 required error when trying to save warm phase with -1 for shrink', async () => {
       const rendered = mountWithIntl(component);
       await noRollover(rendered);
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'warm');
-      setPhaseAfter(rendered, 'warm', '1');
-      findTestSubject(rendered, 'shrinkSwitch').simulate('click');
-      rendered.update();
-      const shrinkInput = rendered.find('input#warm-selectedPrimaryShardCount');
-      shrinkInput.simulate('change', { target: { value: '-1' } });
+      await setPhaseAfter(rendered, 'warm', '1');
+      act(() => {
+        findTestSubject(rendered, 'shrinkSwitch').simulate('click');
+      });
       rendered.update();
-      await save(rendered);
-      expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]);
+      const shrinkInput = findTestSubject(rendered, 'warm-selectedPrimaryShardCount');
+      await act(async () => {
+        shrinkInput.simulate('change', { target: { value: '-1' } });
+      });
+      waitForFormLibValidation(rendered);
+      expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]);
     });
     test('should show positive number required above zero error when trying to save warm phase with 0 for force merge', async () => {
       const rendered = mountWithIntl(component);
       await noRollover(rendered);
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'warm');
-      setPhaseAfter(rendered, 'warm', '1');
-      findTestSubject(rendered, 'warm-forceMergeSwitch').simulate('click');
+      await setPhaseAfter(rendered, 'warm', '1');
+      act(() => {
+        findTestSubject(rendered, 'warm-forceMergeSwitch').simulate('click');
+      });
       rendered.update();
       const forcemergeInput = findTestSubject(rendered, 'warm-selectedForceMergeSegments');
-      forcemergeInput.simulate('change', { target: { value: '0' } });
-      rendered.update();
-      await save(rendered);
-      expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]);
+      await act(async () => {
+        forcemergeInput.simulate('change', { target: { value: '0' } });
+      });
+      waitForFormLibValidation(rendered);
+      expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]);
     });
     test('should show positive number above 0 required error when trying to save warm phase with -1 for force merge', async () => {
       const rendered = mountWithIntl(component);
       await noRollover(rendered);
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'warm');
-      setPhaseAfter(rendered, 'warm', '1');
-      findTestSubject(rendered, 'warm-forceMergeSwitch').simulate('click');
+      await setPhaseAfter(rendered, 'warm', '1');
+      await act(async () => {
+        findTestSubject(rendered, 'warm-forceMergeSwitch').simulate('click');
+      });
       rendered.update();
       const forcemergeInput = findTestSubject(rendered, 'warm-selectedForceMergeSegments');
-      forcemergeInput.simulate('change', { target: { value: '-1' } });
-      rendered.update();
-      await save(rendered);
-      expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]);
+      await act(async () => {
+        forcemergeInput.simulate('change', { target: { value: '-1' } });
+      });
+      waitForFormLibValidation(rendered);
+      expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]);
     });
     test('should show spinner for node attributes input when loading', async () => {
       server.respondImmediately = false;
@@ -504,7 +519,7 @@ describe('edit policy', () => {
       await activatePhase(rendered, 'warm');
       expect(rendered.find('.euiLoadingSpinner').exists()).toBeTruthy();
       expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy();
-      expect(getNodeAttributeSelect(rendered, 'warm').exists()).toBeFalsy();
+      expect(getNodeAttributeSelectLegacy(rendered, 'warm').exists()).toBeFalsy();
     });
     test('should show warning instead of node attributes input when none exist', async () => {
       http.setupNodeListResponse({
@@ -517,9 +532,9 @@ describe('edit policy', () => {
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'warm');
       expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
-      openNodeAttributesSection(rendered, 'warm');
+      await openNodeAttributesSection(rendered, 'warm');
       expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeTruthy();
-      expect(getNodeAttributeSelect(rendered, 'warm').exists()).toBeFalsy();
+      expect(getNodeAttributeSelectLegacy(rendered, 'warm').exists()).toBeFalsy();
     });
     test('should show node attributes input when attributes exist', async () => {
       const rendered = mountWithIntl(component);
@@ -527,7 +542,7 @@ describe('edit policy', () => {
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'warm');
       expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
-      openNodeAttributesSection(rendered, 'warm');
+      await openNodeAttributesSection(rendered, 'warm');
       expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeFalsy();
       const nodeAttributesSelect = getNodeAttributeSelect(rendered, 'warm');
       expect(nodeAttributesSelect.exists()).toBeTruthy();
@@ -539,13 +554,15 @@ describe('edit policy', () => {
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'warm');
       expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
-      openNodeAttributesSection(rendered, 'warm');
+      await openNodeAttributesSection(rendered, 'warm');
       expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeFalsy();
       const nodeAttributesSelect = getNodeAttributeSelect(rendered, 'warm');
       expect(nodeAttributesSelect.exists()).toBeTruthy();
       expect(findTestSubject(rendered, 'warm-viewNodeDetailsFlyoutButton').exists()).toBeFalsy();
       expect(nodeAttributesSelect.find('option').length).toBe(2);
-      nodeAttributesSelect.simulate('change', { target: { value: 'attribute:true' } });
+      await act(async () => {
+        nodeAttributesSelect.simulate('change', { target: { value: 'attribute:true' } });
+      });
       rendered.update();
       const flyoutButton = findTestSubject(rendered, 'warm-viewNodeDetailsFlyoutButton');
       expect(flyoutButton.exists()).toBeTruthy();
@@ -608,7 +625,7 @@ describe('edit policy', () => {
       await noRollover(rendered);
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'cold');
-      setPhaseAfter(rendered, 'cold', '0');
+      setPhaseAfterLegacy(rendered, 'cold', '0');
       await save(rendered);
       expectedErrorMessages(rendered, []);
     });
@@ -617,7 +634,7 @@ describe('edit policy', () => {
       await noRollover(rendered);
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'cold');
-      setPhaseAfter(rendered, 'cold', '-1');
+      setPhaseAfterLegacy(rendered, 'cold', '-1');
       await save(rendered);
       expectedErrorMessages(rendered, [positiveNumberRequiredMessage]);
     });
@@ -629,7 +646,7 @@ describe('edit policy', () => {
       await activatePhase(rendered, 'cold');
       expect(rendered.find('.euiLoadingSpinner').exists()).toBeTruthy();
       expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy();
-      expect(getNodeAttributeSelect(rendered, 'cold').exists()).toBeFalsy();
+      expect(getNodeAttributeSelectLegacy(rendered, 'cold').exists()).toBeFalsy();
     });
     test('should show warning instead of node attributes input when none exist', async () => {
       http.setupNodeListResponse({
@@ -642,9 +659,9 @@ describe('edit policy', () => {
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'cold');
       expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
-      openNodeAttributesSection(rendered, 'cold');
+      await openNodeAttributesSection(rendered, 'cold');
       expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeTruthy();
-      expect(getNodeAttributeSelect(rendered, 'cold').exists()).toBeFalsy();
+      expect(getNodeAttributeSelectLegacy(rendered, 'cold').exists()).toBeFalsy();
     });
     test('should show node attributes input when attributes exist', async () => {
       const rendered = mountWithIntl(component);
@@ -652,9 +669,9 @@ describe('edit policy', () => {
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'cold');
       expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
-      openNodeAttributesSection(rendered, 'cold');
+      await openNodeAttributesSection(rendered, 'cold');
       expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeFalsy();
-      const nodeAttributesSelect = getNodeAttributeSelect(rendered, 'cold');
+      const nodeAttributesSelect = getNodeAttributeSelectLegacy(rendered, 'cold');
       expect(nodeAttributesSelect.exists()).toBeTruthy();
       expect(nodeAttributesSelect.find('option').length).toBe(2);
     });
@@ -664,9 +681,9 @@ describe('edit policy', () => {
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'cold');
       expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
-      openNodeAttributesSection(rendered, 'cold');
+      await openNodeAttributesSection(rendered, 'cold');
       expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeFalsy();
-      const nodeAttributesSelect = getNodeAttributeSelect(rendered, 'cold');
+      const nodeAttributesSelect = getNodeAttributeSelectLegacy(rendered, 'cold');
       expect(nodeAttributesSelect.exists()).toBeTruthy();
       expect(findTestSubject(rendered, 'cold-viewNodeDetailsFlyoutButton').exists()).toBeFalsy();
       expect(nodeAttributesSelect.find('option').length).toBe(2);
@@ -685,7 +702,7 @@ describe('edit policy', () => {
       await noRollover(rendered);
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'cold');
-      setPhaseAfter(rendered, 'cold', '1');
+      setPhaseAfterLegacy(rendered, 'cold', '1');
       setPhaseIndexPriorityLegacy(rendered, 'cold', '-1');
       await save(rendered);
       expectedErrorMessages(rendered, [positiveNumberRequiredMessage]);
@@ -736,7 +753,7 @@ describe('edit policy', () => {
       await noRollover(rendered);
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'delete');
-      setPhaseAfter(rendered, 'delete', '0');
+      setPhaseAfterLegacy(rendered, 'delete', '0');
       await save(rendered);
       expectedErrorMessages(rendered, []);
     });
@@ -745,7 +762,7 @@ describe('edit policy', () => {
       await noRollover(rendered);
       setPolicyName(rendered, 'mypolicy');
       await activatePhase(rendered, 'delete');
-      setPhaseAfter(rendered, 'delete', '-1');
+      setPhaseAfterLegacy(rendered, 'delete', '-1');
       await save(rendered);
       expectedErrorMessages(rendered, [positiveNumberRequiredMessage]);
     });
@@ -796,7 +813,8 @@ describe('edit policy', () => {
       test('should hide data tier option on cloud using legacy node role configuration', async () => {
         http.setupNodeListResponse({
           nodesByAttributes: { test: ['123'] },
-          nodesByRoles: { data: ['test'], data_hot: ['test'], data_warm: ['test'] },
+          // On cloud, if using legacy config there will not be any "data_*" roles set.
+          nodesByRoles: { data: ['test'] },
           isUsingDeprecatedDataRoleConfig: true,
         });
         const rendered = mountWithIntl(component);
diff --git a/x-pack/plugins/index_lifecycle_management/common/constants/data_tiers.ts b/x-pack/plugins/index_lifecycle_management/common/constants/data_tiers.ts
index 8a1acf72949e6..f6b9506f9068c 100644
--- a/x-pack/plugins/index_lifecycle_management/common/constants/data_tiers.ts
+++ b/x-pack/plugins/index_lifecycle_management/common/constants/data_tiers.ts
@@ -6,13 +6,13 @@
 
 // Order of node roles matters here, the warm phase prefers allocating data
 // to the data_warm role.
-import { NodeDataRole, PhaseWithAllocation } from '../types';
+import { DataTierRole, PhaseWithAllocation } from '../types';
 
-const WARM_PHASE_NODE_PREFERENCE: NodeDataRole[] = ['data_warm', 'data_hot'];
+const WARM_PHASE_NODE_PREFERENCE: DataTierRole[] = ['data_warm', 'data_hot'];
 
-const COLD_PHASE_NODE_PREFERENCE: NodeDataRole[] = ['data_cold', 'data_warm', 'data_hot'];
+const COLD_PHASE_NODE_PREFERENCE: DataTierRole[] = ['data_cold', 'data_warm', 'data_hot'];
 
-export const phaseToNodePreferenceMap: Record<PhaseWithAllocation, NodeDataRole[]> = Object.freeze({
+export const phaseToNodePreferenceMap: Record<PhaseWithAllocation, DataTierRole[]> = Object.freeze({
   warm: WARM_PHASE_NODE_PREFERENCE,
   cold: COLD_PHASE_NODE_PREFERENCE,
 });
diff --git a/x-pack/plugins/index_lifecycle_management/common/types/api.ts b/x-pack/plugins/index_lifecycle_management/common/types/api.ts
index ccdd7fcb11778..b7ca16ac46dde 100644
--- a/x-pack/plugins/index_lifecycle_management/common/types/api.ts
+++ b/x-pack/plugins/index_lifecycle_management/common/types/api.ts
@@ -4,11 +4,11 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-import { NodeDataRoleWithCatchAll } from '.';
+import { AnyDataRole } from '.';
 
 export interface ListNodesRouteResponse {
   nodesByAttributes: { [attributePair: string]: string[] };
-  nodesByRoles: { [role in NodeDataRoleWithCatchAll]?: string[] };
+  nodesByRoles: { [role in AnyDataRole]?: string[] };
 
   /**
    * A flag to indicate whether a node is using `settings.node.data` which is the now deprecated way cloud configured
diff --git a/x-pack/plugins/index_lifecycle_management/common/types/index.ts b/x-pack/plugins/index_lifecycle_management/common/types/index.ts
index 1f41370e48f18..737e5a551aae8 100644
--- a/x-pack/plugins/index_lifecycle_management/common/types/index.ts
+++ b/x-pack/plugins/index_lifecycle_management/common/types/index.ts
@@ -9,8 +9,17 @@ export * from './api';
 export * from './policies';
 
 /**
- * These roles reflect how nodes are stratified into different data tiers. The "data" role
- * is a catch-all that can be used to store data in any phase.
+ * These roles reflect how nodes are stratified into different data tiers.
  */
-export type NodeDataRole = 'data_hot' | 'data_warm' | 'data_cold';
-export type NodeDataRoleWithCatchAll = 'data' | NodeDataRole;
+export type DataTierRole = 'data_hot' | 'data_warm' | 'data_cold';
+
+/**
+ * The "data_content" role can store all data the ES stack uses for feature
+ * functionality like security-related indices.
+ */
+export type DataRole = 'data_content' | DataTierRole;
+
+/**
+ * The "data" role can store data allocated to any tier.
+ */
+export type AnyDataRole = 'data' | DataRole;
diff --git a/x-pack/plugins/index_lifecycle_management/common/types/policies.ts b/x-pack/plugins/index_lifecycle_management/common/types/policies.ts
index 152c5e4e9e0d7..813fcd9c253f1 100644
--- a/x-pack/plugins/index_lifecycle_management/common/types/policies.ts
+++ b/x-pack/plugins/index_lifecycle_management/common/types/policies.ts
@@ -35,6 +35,19 @@ export interface SerializedPhase {
   };
 }
 
+export interface MigrateAction {
+  /**
+   * If enabled is ever set it will probably only be set to `false` because the default value
+   * for this is `true`. Rather leave unspecified for true when serialising.
+   */
+  enabled: boolean;
+}
+
+export interface SerializedActionWithAllocation {
+  allocate?: AllocateAction;
+  migrate?: MigrateAction;
+}
+
 export interface SerializedHotPhase extends SerializedPhase {
   actions: {
     rollover?: {
@@ -59,7 +72,7 @@ export interface SerializedWarmPhase extends SerializedPhase {
     set_priority?: {
       priority: number | null;
     };
-    migrate?: { enabled: boolean };
+    migrate?: MigrateAction;
   };
 }
 
@@ -70,7 +83,7 @@ export interface SerializedColdPhase extends SerializedPhase {
     set_priority?: {
       priority: number | null;
     };
-    migrate?: { enabled: boolean };
+    migrate?: MigrateAction;
   };
 }
 
@@ -87,18 +100,11 @@ export interface SerializedDeletePhase extends SerializedPhase {
 
 export interface AllocateAction {
   number_of_replicas?: number;
-  include: {};
-  exclude: {};
+  include?: {};
+  exclude?: {};
   require?: {
     [attribute: string]: string;
   };
-  migrate?: {
-    /**
-     * If enabled is ever set it will only be set to `false` because the default value
-     * for this is `true`. Rather leave unspecified for true.
-     */
-    enabled: false;
-  };
 }
 
 export interface ForcemergeAction {
@@ -110,7 +116,6 @@ export interface ForcemergeAction {
 export interface LegacyPolicy {
   name: string;
   phases: {
-    warm: WarmPhase;
     cold: ColdPhase;
     delete: DeletePhase;
   };
@@ -154,17 +159,6 @@ export interface PhaseWithForcemergeAction {
   bestCompressionEnabled: boolean;
 }
 
-export interface WarmPhase
-  extends CommonPhaseSettings,
-    PhaseWithMinAge,
-    PhaseWithAllocationAction,
-    PhaseWithIndexPriority,
-    PhaseWithForcemergeAction {
-  warmPhaseOnRollover: boolean;
-  shrinkEnabled: boolean;
-  selectedPrimaryShardCount: string;
-}
-
 export interface ColdPhase
   extends CommonPhaseSettings,
     PhaseWithMinAge,
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts b/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts
index c919331082ec3..136b68727672a 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts
@@ -4,16 +4,12 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-import {
-  SerializedPhase,
-  ColdPhase,
-  DeletePhase,
-  WarmPhase,
-  SerializedPolicy,
-} from '../../../common/types';
+import { SerializedPhase, ColdPhase, DeletePhase, SerializedPolicy } from '../../../common/types';
 
 export const defaultSetPriority: string = '100';
 
+export const defaultPhaseIndexPriority: string = '50';
+
 export const defaultPolicy: SerializedPolicy = {
   name: '',
   phases: {
@@ -28,22 +24,6 @@ export const defaultPolicy: SerializedPolicy = {
   },
 };
 
-export const defaultNewWarmPhase: WarmPhase = {
-  phaseEnabled: false,
-  forceMergeEnabled: false,
-  selectedForceMergeSegments: '',
-  bestCompressionEnabled: false,
-  selectedMinimumAge: '0',
-  selectedMinimumAgeUnits: 'd',
-  selectedNodeAttrs: '',
-  shrinkEnabled: false,
-  selectedPrimaryShardCount: '',
-  selectedReplicaCount: '',
-  warmPhaseOnRollover: true,
-  phaseIndexPriority: '50',
-  dataTierAllocationType: 'default',
-};
-
 export const defaultNewColdPhase: ColdPhase = {
   phaseEnabled: false,
   selectedMinimumAge: '0',
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/determine_allocation_type.ts b/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/determine_allocation_type.ts
index 4067ad97fc43b..20ac439e9964f 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/determine_allocation_type.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/determine_allocation_type.ts
@@ -4,31 +4,63 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-import { DataTierAllocationType, AllocateAction } from '../../../../common/types';
+import { DataTierAllocationType, AllocateAction, MigrateAction } from '../../../../common/types';
 
 /**
  * Determine what deserialized state the policy config represents.
  *
  * See {@DataTierAllocationType} for more information.
  */
-export const determineDataTierAllocationType = (
-  allocateAction?: AllocateAction
+export const determineDataTierAllocationTypeLegacy = (
+  actions: {
+    allocate?: AllocateAction;
+    migrate?: MigrateAction;
+  } = {}
 ): DataTierAllocationType => {
-  if (!allocateAction) {
-    return 'default';
-  }
+  const { allocate, migrate } = actions;
 
-  if (allocateAction.migrate?.enabled === false) {
+  if (migrate?.enabled === false) {
     return 'none';
   }
 
+  if (!allocate) {
+    return 'default';
+  }
+
   if (
-    (allocateAction.require && Object.keys(allocateAction.require).length) ||
-    (allocateAction.include && Object.keys(allocateAction.include).length) ||
-    (allocateAction.exclude && Object.keys(allocateAction.exclude).length)
+    (allocate.require && Object.keys(allocate.require).length) ||
+    (allocate.include && Object.keys(allocate.include).length) ||
+    (allocate.exclude && Object.keys(allocate.exclude).length)
   ) {
     return 'custom';
   }
 
   return 'default';
 };
+
+export const determineDataTierAllocationType = (
+  actions: {
+    allocate?: AllocateAction;
+    migrate?: MigrateAction;
+  } = {}
+) => {
+  const { allocate, migrate } = actions;
+
+  if (migrate?.enabled === false) {
+    return 'none';
+  }
+
+  if (!allocate) {
+    return 'node_roles';
+  }
+
+  if (
+    (allocate.require && Object.keys(allocate.require).length) ||
+    (allocate.include && Object.keys(allocate.include).length) ||
+    (allocate.exclude && Object.keys(allocate.exclude).length)
+  ) {
+    return 'node_attrs';
+  }
+
+  return 'node_roles';
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/get_available_node_roles_for_phase.ts b/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/get_available_node_roles_for_phase.ts
index 6daae57330886..179de0b1d8c8e 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/get_available_node_roles_for_phase.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/get_available_node_roles_for_phase.ts
@@ -5,14 +5,14 @@
  */
 
 import {
-  NodeDataRole,
+  DataTierRole,
   ListNodesRouteResponse,
   PhaseWithAllocation,
 } from '../../../../common/types';
 
 import { phaseToNodePreferenceMap } from '../../../../common/constants';
 
-export type AllocationNodeRole = NodeDataRole | 'none';
+export type AllocationNodeRole = DataTierRole | 'none';
 
 /**
  * Given a phase and current cluster node roles, determine which nodes the phase
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/index.ts
index 87f2cbc08ecc0..ac1aae270628d 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/index.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/index.ts
@@ -7,3 +7,5 @@
 export * from './determine_allocation_type';
 
 export * from './get_available_node_roles_for_phase';
+
+export * from './is_node_role_first_preference';
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/is_node_role_first_preference.ts b/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/is_node_role_first_preference.ts
index 872efa740b131..fff640a5eb957 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/is_node_role_first_preference.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/lib/data_tiers/is_node_role_first_preference.ts
@@ -4,9 +4,9 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-import { NodeDataRole, PhaseWithAllocation } from '../../../../common/types';
+import { DataTierRole, PhaseWithAllocation } from '../../../../common/types';
 import { phaseToNodePreferenceMap } from '../../../../common/constants';
 
-export const isNodeRoleFirstPreference = (phase: PhaseWithAllocation, nodeRole: NodeDataRole) => {
+export const isNodeRoleFirstPreference = (phase: PhaseWithAllocation, nodeRole: DataTierRole) => {
   return phaseToNodePreferenceMap[phase][0] === nodeRole;
 };
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/default_allocation_notice.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/default_allocation_notice.tsx
index 42f9e8494a0b3..3d0052c69607b 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/default_allocation_notice.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/default_allocation_notice.tsx
@@ -8,11 +8,11 @@ import { i18n } from '@kbn/i18n';
 import React, { FunctionComponent } from 'react';
 import { EuiCallOut } from '@elastic/eui';
 
-import { PhaseWithAllocation, NodeDataRole } from '../../../../../../common/types';
+import { PhaseWithAllocation, DataTierRole } from '../../../../../../common/types';
 
 import { AllocationNodeRole } from '../../../../lib';
 
-const i18nTextsNodeRoleToDataTier: Record<NodeDataRole, string> = {
+const i18nTextsNodeRoleToDataTier: Record<DataTierRole, string> = {
   data_hot: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.dataTierHotLabel', {
     defaultMessage: 'hot',
   }),
@@ -31,7 +31,7 @@ const i18nTexts = {
         'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm.title',
         { defaultMessage: 'No nodes assigned to the warm tier' }
       ),
-      body: (nodeRole: NodeDataRole) =>
+      body: (nodeRole: DataTierRole) =>
         i18n.translate('xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm', {
           defaultMessage:
             'This policy will move data in the warm phase to {tier} tier nodes instead.',
@@ -43,7 +43,7 @@ const i18nTexts = {
         'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.cold.title',
         { defaultMessage: 'No nodes assigned to the cold tier' }
       ),
-      body: (nodeRole: NodeDataRole) =>
+      body: (nodeRole: DataTierRole) =>
         i18n.translate('xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.cold', {
           defaultMessage:
             'This policy will move data in the cold phase to {tier} tier nodes instead.',
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/forcemerge.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/forcemerge_legacy.tsx
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/forcemerge.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/forcemerge_legacy.tsx
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts
index 04d9a6ef3cf67..2b774b00b98a9 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts
@@ -7,11 +7,11 @@
 export { ActiveBadge } from './active_badge';
 export { ErrableFormRow } from './form_errors';
 export { LearnMoreLink } from './learn_more_link';
-export { MinAgeInput } from './min_age_input';
+export { MinAgeInput } from './min_age_input_legacy';
 export { OptionalLabel } from './optional_label';
 export { PhaseErrorMessage } from './phase_error_message';
 export { PolicyJsonFlyout } from './policy_json_flyout';
-export { SetPriorityInput } from './set_priority_input';
+export { SetPriorityInput } from './set_priority_input_legacy';
 export { SnapshotPolicies } from './snapshot_policies';
 export {
   DataTierAllocation,
@@ -21,6 +21,6 @@ export {
   DefaultAllocationNotice,
 } from './data_tier_allocation';
 export { DescribedFormField } from './described_form_field';
-export { Forcemerge } from './forcemerge';
+export { Forcemerge } from './forcemerge_legacy';
 
 export * from './phases';
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/min_age_input.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/min_age_input_legacy.tsx
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/min_age_input.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/min_age_input_legacy.tsx
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase.tsx
index 7a22fb5bc1f0c..da6c358aa67c1 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase.tsx
@@ -28,7 +28,7 @@ import {
   DescribedFormField,
 } from '../';
 
-import { DataTierAllocationField, useRolloverPath } from './shared';
+import { DataTierAllocationFieldLegacy, useRolloverPath } from './shared';
 
 const i18nTexts = {
   freezeLabel: i18n.translate('xpack.indexLifecycleMgmt.coldPhase.freezeIndexLabel', {
@@ -124,7 +124,7 @@ export const ColdPhase: FunctionComponent<Props> = ({
         {phaseData.phaseEnabled ? (
           <Fragment>
             {/* Data tier allocation section */}
-            <DataTierAllocationField
+            <DataTierAllocationFieldLegacy
               description={i18nTexts.dataTierAllocation.description}
               phase={coldProperty}
               setPhaseData={setPhaseData}
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx
index 6a5f946b89b58..a184ddf5148b9 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx
@@ -4,7 +4,7 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-import React, { Fragment, FunctionComponent, useEffect, useState } from 'react';
+import React, { Fragment, FunctionComponent, useState } from 'react';
 import { get } from 'lodash';
 import { FormattedMessage } from '@kbn/i18n/react';
 import { i18n } from '@kbn/i18n';
@@ -27,25 +27,21 @@ import {
   NumericField,
 } from '../../../../../../shared_imports';
 
+import { i18nTexts } from '../../../i18n_texts';
+
 import { ROLLOVER_EMPTY_VALIDATION } from '../../../form_validations';
 
 import { ROLLOVER_FORM_PATHS } from '../../../constants';
 
 import { LearnMoreLink, ActiveBadge, PhaseErrorMessage } from '../../';
 
-import { Forcemerge, SetPriorityInput } from '../shared';
+import { Forcemerge, SetPriorityInput, useRolloverPath } from '../shared';
 
 import { maxSizeStoredUnits, maxAgeUnits } from './constants';
 
-import { i18nTexts } from './i18n_texts';
-
-import { useRolloverPath } from '../shared';
-
 const hotProperty: keyof Phases = 'hot';
 
-export const HotPhase: FunctionComponent<{ setWarmPhaseOnRollover: (v: boolean) => void }> = ({
-  setWarmPhaseOnRollover,
-}) => {
+export const HotPhase: FunctionComponent = () => {
   const form = useFormContext();
   const [formData] = useFormData({
     watch: useRolloverPath,
@@ -55,10 +51,6 @@ export const HotPhase: FunctionComponent<{ setWarmPhaseOnRollover: (v: boolean)
   const isShowingErrors = form.isValid === false;
   const [showEmptyRolloverFieldsError, setShowEmptyRolloverFieldsError] = useState(false);
 
-  useEffect(() => {
-    setWarmPhaseOnRollover(isRolloverEnabled ?? false);
-  }, [setWarmPhaseOnRollover, isRolloverEnabled]);
-
   return (
     <>
       <EuiDescribedFormGroup
@@ -127,11 +119,11 @@ export const HotPhase: FunctionComponent<{ setWarmPhaseOnRollover: (v: boolean)
             {showEmptyRolloverFieldsError && (
               <>
                 <EuiCallOut
-                  title={i18nTexts.rollOverConfigurationCallout.title}
+                  title={i18nTexts.editPolicy.errors.rollOverConfigurationCallout.title}
                   data-test-subj="rolloverSettingsRequired"
                   color="danger"
                 >
-                  <div>{i18nTexts.rollOverConfigurationCallout.body}</div>
+                  <div>{i18nTexts.editPolicy.errors.rollOverConfigurationCallout.body}</div>
                 </EuiCallOut>
                 <EuiSpacer size="s" />
               </>
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/i18n_texts.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/i18n_texts.ts
deleted file mode 100644
index 6423b12b86dd2..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/i18n_texts.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { i18n } from '@kbn/i18n';
-
-export const i18nTexts = {
-  maximumAgeRequiredMessage: i18n.translate(
-    'xpack.indexLifecycleMgmt.editPolicy.maximumAgeMissingError',
-    {
-      defaultMessage: 'A maximum age is required.',
-    }
-  ),
-  maximumSizeRequiredMessage: i18n.translate(
-    'xpack.indexLifecycleMgmt.editPolicy.maximumIndexSizeMissingError',
-    {
-      defaultMessage: 'A maximum index size is required.',
-    }
-  ),
-  maximumDocumentsRequiredMessage: i18n.translate(
-    'xpack.indexLifecycleMgmt.editPolicy.maximumDocumentsMissingError',
-    {
-      defaultMessage: 'Maximum documents is required.',
-    }
-  ),
-  rollOverConfigurationCallout: {
-    title: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.rolloverConfigurationError.title', {
-      defaultMessage: 'Invalid rollover configuration',
-    }),
-    body: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.rolloverConfigurationError.body', {
-      defaultMessage:
-        'A value for one of maximum size, maximum documents, or maximum age is required.',
-    }),
-  },
-};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/cloud_data_tier_callout.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/cloud_data_tier_callout.tsx
new file mode 100644
index 0000000000000..2dff55ac10de1
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/cloud_data_tier_callout.tsx
@@ -0,0 +1,26 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { i18n } from '@kbn/i18n';
+import React, { FunctionComponent } from 'react';
+import { EuiCallOut } from '@elastic/eui';
+
+const i18nTexts = {
+  title: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.title', {
+    defaultMessage: 'Create a cold tier',
+  }),
+  body: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.body', {
+    defaultMessage: 'Edit your Elastic Cloud deployment to set up a cold tier.',
+  }),
+};
+
+export const CloudDataTierCallout: FunctionComponent = () => {
+  return (
+    <EuiCallOut title={i18nTexts.title} data-test-subj="cloudDataTierCallout">
+      {i18nTexts.body}
+    </EuiCallOut>
+  );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/data_tier_allocation.scss b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/data_tier_allocation.scss
new file mode 100644
index 0000000000000..62ec3f303e1e8
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/data_tier_allocation.scss
@@ -0,0 +1,9 @@
+.indexLifecycleManagement__phase__dataTierAllocation {
+  &__controlSection {
+    background-color: $euiColorLightestShade;
+    padding-top: $euiSizeM;
+    padding-left: $euiSizeM;
+    padding-right: $euiSizeM;
+    padding-bottom: $euiSizeM;
+  }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/data_tier_allocation.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/data_tier_allocation.tsx
new file mode 100644
index 0000000000000..56af4bbac7a26
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/data_tier_allocation.tsx
@@ -0,0 +1,191 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { FunctionComponent } from 'react';
+import { get } from 'lodash';
+import { i18n } from '@kbn/i18n';
+import { EuiText, EuiSpacer, EuiSuperSelectOption } from '@elastic/eui';
+
+import { UseField, SuperSelectField, useFormData } from '../../../../../../../../shared_imports';
+import { PhaseWithAllocation } from '../../../../../../../../../common/types';
+
+import { DataTierAllocationType } from '../../../../../types';
+
+import { NodeAllocation } from './node_allocation';
+import { SharedProps } from './types';
+
+import './data_tier_allocation.scss';
+
+type SelectOptions = EuiSuperSelectOption<DataTierAllocationType>;
+
+const i18nTexts = {
+  allocationOptions: {
+    warm: {
+      default: {
+        input: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.defaultOption.input',
+          { defaultMessage: 'Use warm nodes (recommended)' }
+        ),
+        helpText: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.defaultOption.helpText',
+          { defaultMessage: 'Move data to nodes in the warm tier.' }
+        ),
+      },
+      none: {
+        inputDisplay: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.noneOption.input',
+          { defaultMessage: 'Off' }
+        ),
+        helpText: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.noneOption.helpText',
+          { defaultMessage: 'Do not move data in the warm phase.' }
+        ),
+      },
+      custom: {
+        inputDisplay: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.customOption.input',
+          { defaultMessage: 'Custom' }
+        ),
+        helpText: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.customOption.helpText',
+          { defaultMessage: 'Move data based on node attributes.' }
+        ),
+      },
+    },
+    cold: {
+      default: {
+        input: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.defaultOption.input',
+          { defaultMessage: 'Use cold nodes (recommended)' }
+        ),
+        helpText: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.defaultOption.helpText',
+          { defaultMessage: 'Move data to nodes in the cold tier.' }
+        ),
+      },
+      none: {
+        inputDisplay: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.noneOption.input',
+          { defaultMessage: 'Off' }
+        ),
+        helpText: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.noneOption.helpText',
+          { defaultMessage: 'Do not move data in the cold phase.' }
+        ),
+      },
+      custom: {
+        inputDisplay: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.input',
+          { defaultMessage: 'Custom' }
+        ),
+        helpText: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.helpText',
+          { defaultMessage: 'Move data based on node attributes.' }
+        ),
+      },
+    },
+  },
+};
+
+const getSelectOptions = (phase: PhaseWithAllocation, disableDataTierOption: boolean) =>
+  [
+    disableDataTierOption
+      ? undefined
+      : {
+          'data-test-subj': 'defaultDataAllocationOption',
+          value: 'node_roles',
+          inputDisplay: i18nTexts.allocationOptions[phase].default.input,
+          dropdownDisplay: (
+            <>
+              <strong>{i18nTexts.allocationOptions[phase].default.input}</strong>
+              <EuiText size="s" color="subdued">
+                <p className="euiTextColor--subdued">
+                  {i18nTexts.allocationOptions[phase].default.helpText}
+                </p>
+              </EuiText>
+            </>
+          ),
+        },
+    {
+      'data-test-subj': 'customDataAllocationOption',
+      value: 'node_attrs',
+      inputDisplay: i18nTexts.allocationOptions[phase].custom.inputDisplay,
+      dropdownDisplay: (
+        <>
+          <strong>{i18nTexts.allocationOptions[phase].custom.inputDisplay}</strong>
+          <EuiText size="s" color="subdued">
+            <p className="euiTextColor--subdued">
+              {i18nTexts.allocationOptions[phase].custom.helpText}
+            </p>
+          </EuiText>
+        </>
+      ),
+    },
+    {
+      'data-test-subj': 'noneDataAllocationOption',
+      value: 'none',
+      inputDisplay: i18nTexts.allocationOptions[phase].none.inputDisplay,
+      dropdownDisplay: (
+        <>
+          <strong>{i18nTexts.allocationOptions[phase].none.inputDisplay}</strong>
+          <EuiText size="s" color="subdued">
+            <p className="euiTextColor--subdued">
+              {i18nTexts.allocationOptions[phase].none.helpText}
+            </p>
+          </EuiText>
+        </>
+      ),
+    },
+  ].filter(Boolean) as SelectOptions[];
+
+export const DataTierAllocation: FunctionComponent<SharedProps> = (props) => {
+  const { phase, hasNodeAttributes, disableDataTierOption } = props;
+
+  const dataTierAllocationTypePath = `_meta.${phase}.dataTierAllocationType`;
+
+  const [formData] = useFormData({
+    watch: dataTierAllocationTypePath,
+  });
+
+  const dataTierAllocationType = get(formData, dataTierAllocationTypePath);
+
+  return (
+    <div data-test-subj={`${phase}-dataTierAllocationControls`}>
+      <UseField path={dataTierAllocationTypePath}>
+        {(field) => {
+          /**
+           * We reset the value to "custom" if we deserialized to "default".
+           *
+           * It would be better if we had all the information we needed before deserializing and
+           * were able to handle this at the deserialization step instead of patching further down
+           * the component tree - this should be a future refactor.
+           */
+          if (disableDataTierOption && field.value === 'node_roles') {
+            field.setValue('node_attrs');
+          }
+          return (
+            <SuperSelectField
+              field={field}
+              euiFieldProps={{
+                hasDividers: true,
+                'data-test-subj': 'dataTierSelect',
+                options: getSelectOptions(phase, disableDataTierOption),
+              }}
+            />
+          );
+        }}
+      </UseField>
+      {dataTierAllocationType === 'node_attrs' && hasNodeAttributes && (
+        <>
+          <EuiSpacer size="s" />
+          <div className="indexLifecycleManagement__phase__dataTierAllocation__controlSection">
+            <NodeAllocation {...props} />
+          </div>
+        </>
+      )}
+    </div>
+  );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/default_allocation_notice.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/default_allocation_notice.tsx
new file mode 100644
index 0000000000000..f1f8fef62f1f8
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/default_allocation_notice.tsx
@@ -0,0 +1,106 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { i18n } from '@kbn/i18n';
+import React, { FunctionComponent } from 'react';
+import { EuiCallOut } from '@elastic/eui';
+
+import { PhaseWithAllocation, DataTierRole } from '../../../../../../../../../common/types';
+
+import { AllocationNodeRole } from '../../../../../../../lib';
+
+const i18nTextsNodeRoleToDataTier: Record<DataTierRole, string> = {
+  data_hot: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.dataTierHotLabel', {
+    defaultMessage: 'hot',
+  }),
+  data_warm: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.dataTierWarmLabel', {
+    defaultMessage: 'warm',
+  }),
+  data_cold: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.dataTierColdLabel', {
+    defaultMessage: 'cold',
+  }),
+};
+
+const i18nTexts = {
+  notice: {
+    warm: {
+      title: i18n.translate(
+        'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm.title',
+        { defaultMessage: 'No nodes assigned to the warm tier' }
+      ),
+      body: (nodeRole: DataTierRole) =>
+        i18n.translate('xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm', {
+          defaultMessage:
+            'This policy will move data in the warm phase to {tier} tier nodes instead.',
+          values: { tier: i18nTextsNodeRoleToDataTier[nodeRole] },
+        }),
+    },
+    cold: {
+      title: i18n.translate(
+        'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.cold.title',
+        { defaultMessage: 'No nodes assigned to the cold tier' }
+      ),
+      body: (nodeRole: DataTierRole) =>
+        i18n.translate('xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.cold', {
+          defaultMessage:
+            'This policy will move data in the cold phase to {tier} tier nodes instead.',
+          values: { tier: i18nTextsNodeRoleToDataTier[nodeRole] },
+        }),
+    },
+  },
+  warning: {
+    warm: {
+      title: i18n.translate(
+        'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableTitle',
+        { defaultMessage: 'No nodes assigned to the warm tier' }
+      ),
+      body: i18n.translate(
+        'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableBody',
+        {
+          defaultMessage:
+            'Assign at least one node to the warm or hot tier to use role-based allocation. The policy will fail to complete allocation if there are no available nodes.',
+        }
+      ),
+    },
+    cold: {
+      title: i18n.translate(
+        'xpack.indexLifecycleMgmt.coldPhase.dataTier.defaultAllocationNotAvailableTitle',
+        { defaultMessage: 'No nodes assigned to the cold tier' }
+      ),
+      body: i18n.translate(
+        'xpack.indexLifecycleMgmt.coldPhase.dataTier.defaultAllocationNotAvailableBody',
+        {
+          defaultMessage:
+            'Assign at least one node to the cold, warm, or hot tier to use role-based allocation. The policy will fail to complete allocation if there are no available nodes.',
+        }
+      ),
+    },
+  },
+};
+
+interface Props {
+  phase: PhaseWithAllocation;
+  targetNodeRole: AllocationNodeRole;
+}
+
+export const DefaultAllocationNotice: FunctionComponent<Props> = ({ phase, targetNodeRole }) => {
+  const content =
+    targetNodeRole === 'none' ? (
+      <EuiCallOut
+        data-test-subj="defaultAllocationWarning"
+        title={i18nTexts.warning[phase].title}
+        color="warning"
+      >
+        {i18nTexts.warning[phase].body}
+      </EuiCallOut>
+    ) : (
+      <EuiCallOut data-test-subj="defaultAllocationNotice" title={i18nTexts.notice[phase].title}>
+        {i18nTexts.notice[phase].body(targetNodeRole)}
+      </EuiCallOut>
+    );
+
+  return content;
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/index.ts
new file mode 100644
index 0000000000000..0782782e77fad
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/index.ts
@@ -0,0 +1,19 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { NodesDataProvider } from './node_data_provider';
+
+export { NodeAllocation } from './node_allocation';
+
+export { NodeAttrsDetails } from './node_attrs_details';
+
+export { DataTierAllocation } from './data_tier_allocation';
+
+export { DefaultAllocationNotice } from './default_allocation_notice';
+
+export { NoNodeAttributesWarning } from './no_node_attributes_warning';
+
+export { CloudDataTierCallout } from './cloud_data_tier_callout';
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx
new file mode 100644
index 0000000000000..338e5367a1d0d
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx
@@ -0,0 +1,50 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { FunctionComponent } from 'react';
+import { EuiCallOut } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+import { PhaseWithAllocation } from '../../../../../../../../../common/types';
+
+const i18nTexts = {
+  title: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingLabel', {
+    defaultMessage: 'No custom node attributes configured',
+  }),
+  warm: {
+    body: i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.warm.nodeAttributesMissingDescription',
+      {
+        defaultMessage:
+          'Define custom node attributes in elasticsearch.yml to use attribute-based allocation. Warm nodes will be used instead.',
+      }
+    ),
+  },
+  cold: {
+    body: i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.cold.nodeAttributesMissingDescription',
+      {
+        defaultMessage:
+          'Define custom node attributes in elasticsearch.yml to use attribute-based allocation. Cold nodes will be used instead.',
+      }
+    ),
+  },
+};
+
+export const NoNodeAttributesWarning: FunctionComponent<{ phase: PhaseWithAllocation }> = ({
+  phase,
+}) => {
+  return (
+    <EuiCallOut
+      data-test-subj="noNodeAttributesWarning"
+      style={{ maxWidth: 400 }}
+      title={i18nTexts.title}
+      color="warning"
+    >
+      {i18nTexts[phase].body}
+    </EuiCallOut>
+  );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_allocation.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_allocation.tsx
new file mode 100644
index 0000000000000..407bb9ea92e85
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_allocation.tsx
@@ -0,0 +1,119 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { useState, FunctionComponent } from 'react';
+import { get } from 'lodash';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { i18n } from '@kbn/i18n';
+import { EuiButtonEmpty, EuiText, EuiSpacer } from '@elastic/eui';
+
+import { PhaseWithAllocationAction } from '../../../../../../../../../common/types';
+
+import { UseField, SelectField, useFormData } from '../../../../../../../../shared_imports';
+
+import { propertyof } from '../../../../../../../services/policies/policy_validation';
+
+import { LearnMoreLink } from '../../../../learn_more_link';
+
+import { NodeAttrsDetails } from './node_attrs_details';
+
+import { SharedProps } from './types';
+
+const learnMoreLink = (
+  <LearnMoreLink
+    text={
+      <FormattedMessage
+        id="xpack.indexLifecycleMgmt.editPolicy.learnAboutShardAllocationLink"
+        defaultMessage="Learn about shard allocation"
+      />
+    }
+    docPath="modules-cluster.html#cluster-shard-allocation-settings"
+  />
+);
+
+const i18nTexts = {
+  doNotModifyAllocationOption: i18n.translate(
+    'xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.doNotModifyAllocationOption',
+    { defaultMessage: 'Do not modify allocation configuration' }
+  ),
+};
+
+export const NodeAllocation: FunctionComponent<SharedProps> = ({ phase, nodes }) => {
+  const allocationNodeAttributePath = `_meta.${phase}.allocationNodeAttribute`;
+
+  const [formData] = useFormData({
+    watch: [allocationNodeAttributePath],
+  });
+
+  const selectedAllocationNodeAttribute = get(formData, allocationNodeAttributePath);
+
+  const [selectedNodeAttrsForDetails, setSelectedNodeAttrsForDetails] = useState<string | null>(
+    null
+  );
+
+  const nodeOptions = Object.keys(nodes).map((attrs) => ({
+    text: `${attrs} (${nodes[attrs].length})`,
+    value: attrs,
+  }));
+
+  nodeOptions.sort((a, b) => a.value.localeCompare(b.value));
+
+  // check that this string is a valid property
+  const nodeAttrsProperty = propertyof<PhaseWithAllocationAction>('selectedNodeAttrs');
+
+  return (
+    <>
+      <EuiText size="s">
+        <p>
+          <FormattedMessage
+            id="xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.customOption.description"
+            defaultMessage="Use node attributes to control shard allocation. {learnMoreLink}."
+            values={{ learnMoreLink }}
+          />
+        </p>
+      </EuiText>
+      <EuiSpacer size="m" />
+
+      {/*
+        TODO: this field component must be revisited to support setting multiple require values and to support
+        setting `include and exclude values on ILM policies. See https://github.com/elastic/kibana/issues/77344
+      */}
+      <UseField
+        path={`_meta.${phase}.allocationNodeAttribute`}
+        component={SelectField}
+        componentProps={{
+          helpText: !!selectedAllocationNodeAttribute ? (
+            <EuiButtonEmpty
+              size="xs"
+              style={{ maxWidth: 400 }}
+              data-test-subj={`${phase}-viewNodeDetailsFlyoutButton`}
+              flush="left"
+              onClick={() => setSelectedNodeAttrsForDetails(selectedAllocationNodeAttribute)}
+            >
+              <FormattedMessage
+                id="xpack.indexLifecycleMgmt.editPolicy.viewNodeDetailsButton"
+                defaultMessage="View nodes with the selected attribute"
+              />
+            </EuiButtonEmpty>
+          ) : undefined,
+          euiFieldProps: {
+            'data-test-subj': `${phase}-${nodeAttrsProperty}`,
+            options: [{ text: i18nTexts.doNotModifyAllocationOption, value: '' }].concat(
+              nodeOptions
+            ),
+            hasNoInitialSelection: false,
+          },
+        }}
+      />
+      {selectedNodeAttrsForDetails ? (
+        <NodeAttrsDetails
+          selectedNodeAttrs={selectedNodeAttrsForDetails}
+          close={() => setSelectedNodeAttrsForDetails(null)}
+        />
+      ) : null}
+    </>
+  );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_attrs_details.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_attrs_details.tsx
new file mode 100644
index 0000000000000..61de977b1cb12
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_attrs_details.tsx
@@ -0,0 +1,106 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+import {
+  EuiFlyoutBody,
+  EuiFlyout,
+  EuiTitle,
+  EuiInMemoryTable,
+  EuiSpacer,
+  EuiPortal,
+  EuiLoadingContent,
+  EuiCallOut,
+  EuiButton,
+} from '@elastic/eui';
+
+import { useLoadNodeDetails } from '../../../../../../../services/api';
+
+interface Props {
+  close: () => void;
+  selectedNodeAttrs: string;
+}
+
+export const NodeAttrsDetails: React.FunctionComponent<Props> = ({ close, selectedNodeAttrs }) => {
+  const { data, isLoading, error, resendRequest } = useLoadNodeDetails(selectedNodeAttrs);
+  let content;
+  if (isLoading) {
+    content = <EuiLoadingContent lines={3} />;
+  } else if (error) {
+    const { statusCode, message } = error;
+    content = (
+      <EuiCallOut
+        title={
+          <FormattedMessage
+            id="xpack.indexLifecycleMgmt.editPolicy.nodeDetailsLoadingFailedTitle"
+            defaultMessage="Unable to load node attribute details"
+          />
+        }
+        color="danger"
+      >
+        <p>
+          {message} ({statusCode})
+        </p>
+        <EuiButton onClick={resendRequest} iconType="refresh" color="danger">
+          <FormattedMessage
+            id="xpack.indexLifecycleMgmt.editPolicy.nodeDetailsReloadButton"
+            defaultMessage="Try again"
+          />
+        </EuiButton>
+      </EuiCallOut>
+    );
+  } else {
+    content = (
+      <EuiInMemoryTable
+        items={data || []}
+        columns={[
+          {
+            field: 'nodeId',
+            name: i18n.translate('xpack.indexLifecycleMgmt.nodeAttrDetails.idField', {
+              defaultMessage: 'ID',
+            }),
+          },
+          {
+            field: 'stats.name',
+            name: i18n.translate('xpack.indexLifecycleMgmt.nodeAttrDetails.nameField', {
+              defaultMessage: 'Name',
+            }),
+          },
+          {
+            field: 'stats.host',
+            name: i18n.translate('xpack.indexLifecycleMgmt.nodeAttrDetails.hostField', {
+              defaultMessage: 'Host',
+            }),
+          },
+        ]}
+        pagination={true}
+        sorting={true}
+      />
+    );
+  }
+  return (
+    <EuiPortal>
+      <EuiFlyout ownFocus onClose={close}>
+        <EuiFlyoutBody>
+          <EuiTitle>
+            <h2>
+              <FormattedMessage
+                id="xpack.indexLifecycleMgmt.nodeAttrDetails.title"
+                defaultMessage="Nodes that contain the attribute {selectedNodeAttrs}"
+                values={{ selectedNodeAttrs }}
+              />
+            </h2>
+          </EuiTitle>
+          <EuiSpacer size="s" />
+          {content}
+        </EuiFlyoutBody>
+      </EuiFlyout>
+    </EuiPortal>
+  );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_data_provider.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_data_provider.tsx
new file mode 100644
index 0000000000000..bb01a42e378fa
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_data_provider.tsx
@@ -0,0 +1,70 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { EuiButton, EuiCallOut, EuiLoadingSpinner, EuiSpacer } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+import { ListNodesRouteResponse } from '../../../../../../../../../common/types';
+import { useLoadNodes } from '../../../../../../../services/api';
+
+interface Props {
+  children: (data: ListNodesRouteResponse) => JSX.Element;
+}
+
+export const NodesDataProvider = ({ children }: Props): JSX.Element => {
+  const { isLoading, data, error, resendRequest } = useLoadNodes();
+
+  if (isLoading) {
+    return (
+      <>
+        <EuiLoadingSpinner size="xl" />
+        <EuiSpacer size="m" />
+      </>
+    );
+  }
+
+  const renderError = () => {
+    if (error) {
+      const { statusCode, message } = error;
+      return (
+        <>
+          <EuiCallOut
+            style={{ maxWidth: 400 }}
+            title={
+              <FormattedMessage
+                id="xpack.indexLifecycleMgmt.editPolicy.nodeAttributesLoadingFailedTitle"
+                defaultMessage="Unable to load node attributes"
+              />
+            }
+            color="danger"
+          >
+            <p>
+              {message} ({statusCode})
+            </p>
+            <EuiButton onClick={resendRequest} iconType="refresh" color="danger">
+              <FormattedMessage
+                id="xpack.indexLifecycleMgmt.editPolicy.nodeAttributesReloadButton"
+                defaultMessage="Try again"
+              />
+            </EuiButton>
+          </EuiCallOut>
+
+          <EuiSpacer size="xl" />
+        </>
+      );
+    }
+    return null;
+  };
+
+  return (
+    <>
+      {renderError()}
+      {/* `data` will always be defined because we use an initial value when loading */}
+      {children(data!)}
+    </>
+  );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/types.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/types.ts
new file mode 100644
index 0000000000000..7bd620757a8ac
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/types.ts
@@ -0,0 +1,22 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import {
+  ListNodesRouteResponse,
+  PhaseWithAllocation,
+} from '../../../../../../../../../common/types';
+
+export interface SharedProps {
+  phase: PhaseWithAllocation;
+  nodes: ListNodesRouteResponse['nodesByAttributes'];
+  hasNodeAttributes: boolean;
+  /**
+   * When on Cloud we want to disable the data tier allocation option when we detect that we are not
+   * using node roles in our Node config yet. See {@link ListNodesRouteResponse} for information about how this is
+   * detected.
+   */
+  disableDataTierOption: boolean;
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/data_tier_allocation_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/data_tier_allocation_field.tsx
new file mode 100644
index 0000000000000..73814537ff276
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/data_tier_allocation_field.tsx
@@ -0,0 +1,137 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { get } from 'lodash';
+import React, { FunctionComponent } from 'react';
+import { i18n } from '@kbn/i18n';
+
+import { EuiDescribedFormGroup, EuiFormRow, EuiSpacer } from '@elastic/eui';
+
+import { useKibana, useFormData } from '../../../../../../../shared_imports';
+
+import { PhaseWithAllocation } from '../../../../../../../../common/types';
+
+import { getAvailableNodeRoleForPhase } from '../../../../../../lib/data_tiers';
+
+import { isNodeRoleFirstPreference } from '../../../../../../lib';
+
+import { DataTierAllocationType } from '../../../../types';
+
+import {
+  DataTierAllocation,
+  DefaultAllocationNotice,
+  NoNodeAttributesWarning,
+  NodesDataProvider,
+  CloudDataTierCallout,
+} from './components';
+
+const i18nTexts = {
+  title: i18n.translate('xpack.indexLifecycleMgmt.common.dataTier.title', {
+    defaultMessage: 'Data allocation',
+  }),
+};
+
+interface Props {
+  phase: PhaseWithAllocation;
+  description: React.ReactNode;
+}
+
+/**
+ * Top-level layout control for the data tier allocation field.
+ */
+export const DataTierAllocationField: FunctionComponent<Props> = ({ phase, description }) => {
+  const {
+    services: { cloud },
+  } = useKibana();
+
+  const dataTierAllocationTypePath = `_meta.${phase}.dataTierAllocationType`;
+  const [formData] = useFormData({ watch: dataTierAllocationTypePath });
+  const allocationType: DataTierAllocationType = get(formData, dataTierAllocationTypePath);
+
+  return (
+    <NodesDataProvider>
+      {({ nodesByRoles, nodesByAttributes, isUsingDeprecatedDataRoleConfig }) => {
+        const hasDataNodeRoles = Object.keys(nodesByRoles).some((nodeRole) =>
+          // match any of the "data_" roles, including data_content.
+          nodeRole.trim().startsWith('data_')
+        );
+        const hasNodeAttrs = Boolean(Object.keys(nodesByAttributes ?? {}).length);
+        const isCloudEnabled = cloud?.isCloudEnabled ?? false;
+
+        const renderNotice = () => {
+          switch (allocationType) {
+            case 'node_roles':
+              if (isCloudEnabled && phase === 'cold') {
+                const isUsingNodeRolesAllocation =
+                  !isUsingDeprecatedDataRoleConfig && hasDataNodeRoles;
+                const hasNoNodesWithNodeRole = !nodesByRoles.data_cold?.length;
+
+                if (isUsingNodeRolesAllocation && hasNoNodesWithNodeRole) {
+                  // Tell cloud users they can deploy nodes on cloud.
+                  return (
+                    <>
+                      <EuiSpacer size="s" />
+                      <CloudDataTierCallout />
+                    </>
+                  );
+                }
+              }
+
+              const allocationNodeRole = getAvailableNodeRoleForPhase(phase, nodesByRoles);
+              if (
+                allocationNodeRole === 'none' ||
+                !isNodeRoleFirstPreference(phase, allocationNodeRole)
+              ) {
+                return (
+                  <>
+                    <EuiSpacer size="s" />
+                    <DefaultAllocationNotice phase={phase} targetNodeRole={allocationNodeRole} />
+                  </>
+                );
+              }
+              break;
+            case 'node_attrs':
+              if (!hasNodeAttrs) {
+                return (
+                  <>
+                    <EuiSpacer size="s" />
+                    <NoNodeAttributesWarning phase={phase} />
+                  </>
+                );
+              }
+              break;
+            default:
+              return null;
+          }
+        };
+
+        return (
+          <EuiDescribedFormGroup
+            title={<h3>{i18nTexts.title}</h3>}
+            description={description}
+            fullWidth
+          >
+            <EuiFormRow>
+              <>
+                <DataTierAllocation
+                  hasNodeAttributes={hasNodeAttrs}
+                  phase={phase}
+                  nodes={nodesByAttributes}
+                  disableDataTierOption={Boolean(
+                    isCloudEnabled && !hasDataNodeRoles && isUsingDeprecatedDataRoleConfig
+                  )}
+                />
+
+                {/* Data tier related warnings and call-to-action notices */}
+                {renderNotice()}
+              </>
+            </EuiFormRow>
+          </EuiDescribedFormGroup>
+        );
+      }}
+    </NodesDataProvider>
+  );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/index.ts
new file mode 100644
index 0000000000000..f9e939058adb9
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/index.ts
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { DataTierAllocationField } from './data_tier_allocation_field';
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_legacy_field.tsx
similarity index 85%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_legacy_field.tsx
index df59efcbfd299..d64df468620e6 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_legacy_field.tsx
@@ -11,8 +11,7 @@ import { EuiDescribedFormGroup, EuiFormRow, EuiSpacer } from '@elastic/eui';
 import { useKibana } from '../../../../../../shared_imports';
 import { PhaseWithAllocationAction, PhaseWithAllocation } from '../../../../../../../common/types';
 import { PhaseValidationErrors } from '../../../../../services/policies/policy_validation';
-import { getAvailableNodeRoleForPhase } from '../../../../../lib/data_tiers';
-import { isNodeRoleFirstPreference } from '../../../../../lib/data_tiers/is_node_role_first_preference';
+import { getAvailableNodeRoleForPhase, isNodeRoleFirstPreference } from '../../../../../lib';
 
 import {
   DataTierAllocation,
@@ -40,7 +39,7 @@ interface Props {
 /**
  * Top-level layout control for the data tier allocation field.
  */
-export const DataTierAllocationField: FunctionComponent<Props> = ({
+export const DataTierAllocationFieldLegacy: FunctionComponent<Props> = ({
   description,
   phase,
   phaseData,
@@ -55,6 +54,10 @@ export const DataTierAllocationField: FunctionComponent<Props> = ({
   return (
     <NodesDataProvider>
       {({ nodesByRoles, nodesByAttributes, isUsingDeprecatedDataRoleConfig }) => {
+        const hasDataNodeRoles = Object.keys(nodesByRoles).some((nodeRole) =>
+          // match any of the "data_" roles, including data_content.
+          nodeRole.trim().startsWith('data_')
+        );
         const hasNodeAttrs = Boolean(Object.keys(nodesByAttributes ?? {}).length);
 
         const renderNotice = () => {
@@ -62,7 +65,8 @@ export const DataTierAllocationField: FunctionComponent<Props> = ({
             case 'default':
               const isCloudEnabled = cloud?.isCloudEnabled ?? false;
               if (isCloudEnabled && phase === 'cold') {
-                const isUsingNodeRolesAllocation = !isUsingDeprecatedDataRoleConfig;
+                const isUsingNodeRolesAllocation =
+                  !isUsingDeprecatedDataRoleConfig && hasDataNodeRoles;
                 const hasNoNodesWithNodeRole = !nodesByRoles.data_cold?.length;
 
                 if (isUsingNodeRolesAllocation && hasNoNodesWithNodeRole) {
@@ -120,9 +124,9 @@ export const DataTierAllocationField: FunctionComponent<Props> = ({
                   phaseData={phaseData}
                   isShowingErrors={isShowingErrors}
                   nodes={nodesByAttributes}
-                  disableDataTierOption={
-                    !!(isUsingDeprecatedDataRoleConfig && cloud?.isCloudEnabled)
-                  }
+                  disableDataTierOption={Boolean(
+                    cloud?.isCloudEnabled && !hasDataNodeRoles && isUsingDeprecatedDataRoleConfig
+                  )}
                 />
 
                 {/* Data tier related warnings and call-to-action notices */}
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/forcemerge_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/forcemerge_field.tsx
index c6f02fd219130..b410bd0e6b3b0 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/forcemerge_field.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/forcemerge_field.tsx
@@ -3,33 +3,32 @@
  * or more contributor license agreements. Licensed under the Elastic License;
  * you may not use this file except in compliance with the Elastic License.
  */
-import { get } from 'lodash';
-import { FormattedMessage } from '@kbn/i18n/react';
-import { EuiDescribedFormGroup, EuiSpacer, EuiTextColor } from '@elastic/eui';
-import React from 'react';
 
-import { Phases } from '../../../../../../../common/types';
+import React, { useMemo } from 'react';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { EuiSpacer, EuiTextColor } from '@elastic/eui';
 
-import { UseField, ToggleField, NumericField, useFormData } from '../../../../../../shared_imports';
+import { UseField, ToggleField, NumericField } from '../../../../../../shared_imports';
 
 import { i18nTexts } from '../../../i18n_texts';
 
-import { LearnMoreLink } from '../../';
+import { useEditPolicyContext } from '../../../edit_policy_context';
+
+import { LearnMoreLink, DescribedFormField } from '../../';
 
 interface Props {
-  phase: keyof Phases & string;
+  phase: 'hot' | 'warm';
 }
 
-const forceMergeEnabledPath = '_meta.hot.forceMergeEnabled';
-
 export const Forcemerge: React.FunctionComponent<Props> = ({ phase }) => {
-  const [formData] = useFormData({
-    watch: forceMergeEnabledPath,
-  });
-  const forceMergeEnabled = get(formData, forceMergeEnabledPath);
+  const { originalPolicy } = useEditPolicyContext();
+
+  const initialToggleValue = useMemo<boolean>(() => {
+    return Boolean(originalPolicy.phases[phase]?.actions?.forcemerge);
+  }, [originalPolicy, phase]);
 
   return (
-    <EuiDescribedFormGroup
+    <DescribedFormField
       title={
         <h3>
           <FormattedMessage
@@ -49,49 +48,40 @@ export const Forcemerge: React.FunctionComponent<Props> = ({ phase }) => {
       }
       titleSize="xs"
       fullWidth
+      switchProps={{
+        'aria-label': i18nTexts.editPolicy.forceMergeEnabledFieldLabel,
+        'data-test-subj': `${phase}-forceMergeSwitch`,
+        'aria-controls': 'forcemergeContent',
+        label: i18nTexts.editPolicy.forceMergeEnabledFieldLabel,
+        initialValue: initialToggleValue,
+      }}
     >
-      <UseField
-        key={forceMergeEnabledPath}
-        path={forceMergeEnabledPath}
-        component={ToggleField}
-        componentProps={{
-          euiFieldProps: {
-            'data-test-subj': `${phase}-forceMergeSwitch`,
-            'aria-label': i18nTexts.editPolicy.forceMergeEnabledFieldLabel,
-            'aria-controls': 'forcemergeContent',
-          },
-        }}
-      />
       <EuiSpacer />
       <div id="forcemergeContent" aria-live="polite" role="region">
-        {forceMergeEnabled && (
-          <>
-            <UseField
-              key={`phases.${phase}.actions.forcemerge.max_num_segments`}
-              path={`phases.${phase}.actions.forcemerge.max_num_segments`}
-              component={NumericField}
-              componentProps={{
-                fullWidth: false,
-                euiFieldProps: {
-                  'data-test-subj': `${phase}-selectedForceMergeSegments`,
-                  min: 1,
-                },
-              }}
-            />
-            <UseField
-              key="_meta.hot.bestCompression"
-              path="_meta.hot.bestCompression"
-              component={ToggleField}
-              componentProps={{
-                hasEmptyLabelSpace: true,
-                euiFieldProps: {
-                  'data-test-subj': `${phase}-bestCompression`,
-                },
-              }}
-            />
-          </>
-        )}
+        <UseField
+          key={`phases.${phase}.actions.forcemerge.max_num_segments`}
+          path={`phases.${phase}.actions.forcemerge.max_num_segments`}
+          component={NumericField}
+          componentProps={{
+            fullWidth: false,
+            euiFieldProps: {
+              'data-test-subj': `${phase}-selectedForceMergeSegments`,
+              min: 1,
+            },
+          }}
+        />
+        <UseField
+          key={`_meta.${phase}.bestCompression`}
+          path={`_meta.${phase}.bestCompression`}
+          component={ToggleField}
+          componentProps={{
+            hasEmptyLabelSpace: true,
+            euiFieldProps: {
+              'data-test-subj': `${phase}-bestCompression`,
+            },
+          }}
+        />
       </div>
-    </EuiDescribedFormGroup>
+    </DescribedFormField>
   );
 };
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/index.ts
index 3b94d36a977d1..0cae3eea6316b 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/index.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/index.ts
@@ -6,8 +6,12 @@
 
 export { useRolloverPath } from '../../../constants';
 
+export { DataTierAllocationFieldLegacy } from './data_tier_allocation_legacy_field';
+
 export { DataTierAllocationField } from './data_tier_allocation_field';
 
 export { Forcemerge } from './forcemerge_field';
 
 export { SetPriorityInput } from './set_priority_input';
+
+export { MinAgeInputField } from './min_age_input_field';
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/min_age_input_field/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/min_age_input_field/index.ts
new file mode 100644
index 0000000000000..0228a524f8129
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/min_age_input_field/index.ts
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { MinAgeInputField } from './min_age_input_field';
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/min_age_input_field/min_age_input_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/min_age_input_field/min_age_input_field.tsx
new file mode 100644
index 0000000000000..f37c387354418
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/min_age_input_field/min_age_input_field.tsx
@@ -0,0 +1,212 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React, { FunctionComponent } from 'react';
+import { get } from 'lodash';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { i18n } from '@kbn/i18n';
+
+import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+
+import {
+  useFormData,
+  UseField,
+  NumericField,
+  SelectField,
+} from '../../../../../../../shared_imports';
+
+import { LearnMoreLink } from '../../../learn_more_link';
+import { useRolloverPath } from '../../../../constants';
+
+import { getUnitsAriaLabelForPhase, getTimingLabelForPhase } from './util';
+
+type PhaseWithMinAgeAction = 'warm' | 'cold' | 'delete';
+
+interface Props {
+  phase: PhaseWithMinAgeAction;
+}
+
+export const MinAgeInputField: FunctionComponent<Props> = ({ phase }): React.ReactElement => {
+  const [formData] = useFormData({ watch: useRolloverPath });
+  const rolloverEnabled = get(formData, useRolloverPath);
+
+  let daysOptionLabel;
+  let hoursOptionLabel;
+  let minutesOptionLabel;
+  let secondsOptionLabel;
+  let millisecondsOptionLabel;
+  let microsecondsOptionLabel;
+  let nanosecondsOptionLabel;
+
+  if (rolloverEnabled) {
+    daysOptionLabel = i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.rolloverDaysOptionLabel',
+      {
+        defaultMessage: 'days from rollover',
+      }
+    );
+
+    hoursOptionLabel = i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.rolloverHoursOptionLabel',
+      {
+        defaultMessage: 'hours from rollover',
+      }
+    );
+    minutesOptionLabel = i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.rolloverMinutesOptionLabel',
+      {
+        defaultMessage: 'minutes from rollover',
+      }
+    );
+
+    secondsOptionLabel = i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.rolloverSecondsOptionLabel',
+      {
+        defaultMessage: 'seconds from rollover',
+      }
+    );
+    millisecondsOptionLabel = i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.rolloverMilliSecondsOptionLabel',
+      {
+        defaultMessage: 'milliseconds from rollover',
+      }
+    );
+
+    microsecondsOptionLabel = i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.rolloverMicroSecondsOptionLabel',
+      {
+        defaultMessage: 'microseconds from rollover',
+      }
+    );
+
+    nanosecondsOptionLabel = i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.rolloverNanoSecondsOptionLabel',
+      {
+        defaultMessage: 'nanoseconds from rollover',
+      }
+    );
+  } else {
+    daysOptionLabel = i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.creationDaysOptionLabel',
+      {
+        defaultMessage: 'days from index creation',
+      }
+    );
+
+    hoursOptionLabel = i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.creationHoursOptionLabel',
+      {
+        defaultMessage: 'hours from index creation',
+      }
+    );
+
+    minutesOptionLabel = i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.creationMinutesOptionLabel',
+      {
+        defaultMessage: 'minutes from index creation',
+      }
+    );
+
+    secondsOptionLabel = i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.creationSecondsOptionLabel',
+      {
+        defaultMessage: 'seconds from index creation',
+      }
+    );
+
+    millisecondsOptionLabel = i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.creationMilliSecondsOptionLabel',
+      {
+        defaultMessage: 'milliseconds from index creation',
+      }
+    );
+
+    microsecondsOptionLabel = i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.creationMicroSecondsOptionLabel',
+      {
+        defaultMessage: 'microseconds from index creation',
+      }
+    );
+
+    nanosecondsOptionLabel = i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.creationNanoSecondsOptionLabel',
+      {
+        defaultMessage: 'nanoseconds from index creation',
+      }
+    );
+  }
+
+  return (
+    <EuiFlexGroup>
+      <EuiFlexItem style={{ maxWidth: 140 }}>
+        <UseField
+          path={`phases.${phase}.min_age`}
+          component={NumericField}
+          componentProps={{
+            label: getTimingLabelForPhase(phase),
+            helpText: (
+              <LearnMoreLink
+                docPath="ilm-index-lifecycle.html#ilm-phase-transitions"
+                text={
+                  <FormattedMessage
+                    id="xpack.indexLifecycleMgmt.editPolicy.learnAboutTimingText"
+                    defaultMessage="Learn about timing"
+                  />
+                }
+              />
+            ),
+            euiFieldProps: {
+              'data-test-subj': `${phase}-selectedMinimumAge`,
+              min: 0,
+            },
+          }}
+        />
+      </EuiFlexItem>
+      <EuiFlexItem style={{ maxWidth: 236 }}>
+        <UseField
+          path={`_meta.${phase}.minAgeUnit`}
+          component={SelectField}
+          componentProps={{
+            hasEmptyLabelSpace: true,
+            euiFieldProps: {
+              'data-test-subj': `${phase}-selectedMinimumAgeUnits`,
+              'aria-label': getUnitsAriaLabelForPhase(phase),
+              options: [
+                {
+                  value: 'd',
+                  text: daysOptionLabel,
+                },
+                {
+                  value: 'h',
+                  text: hoursOptionLabel,
+                },
+                {
+                  value: 'm',
+                  text: minutesOptionLabel,
+                },
+                {
+                  value: 's',
+                  text: secondsOptionLabel,
+                },
+                {
+                  value: 'ms',
+                  text: millisecondsOptionLabel,
+                },
+                {
+                  value: 'micros',
+                  text: microsecondsOptionLabel,
+                },
+                {
+                  value: 'nanos',
+                  text: nanosecondsOptionLabel,
+                },
+              ],
+            },
+          }}
+        />
+      </EuiFlexItem>
+    </EuiFlexGroup>
+  );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/min_age_input_field/util.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/min_age_input_field/util.ts
new file mode 100644
index 0000000000000..181894badba7b
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/min_age_input_field/util.ts
@@ -0,0 +1,58 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { i18n } from '@kbn/i18n';
+import { Phases } from '../../../../../../../../common/types';
+
+type PhaseWithMinAgeAction = 'warm' | 'cold' | 'delete';
+
+export function getUnitsAriaLabelForPhase(phase: keyof Phases) {
+  // NOTE: Hot phase isn't necessary, because indices begin in the hot phase.
+  switch (phase) {
+    case 'warm':
+      return i18n.translate(
+        'xpack.indexLifecycleMgmt.editPolicy.phaseWarm.minimumAgeUnitsAriaLabel',
+        {
+          defaultMessage: 'Units for timing of warm phase',
+        }
+      );
+
+    case 'cold':
+      return i18n.translate(
+        'xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeUnitsAriaLabel',
+        {
+          defaultMessage: 'Units for timing of cold phase',
+        }
+      );
+
+    case 'delete':
+      return i18n.translate(
+        'xpack.indexLifecycleMgmt.editPolicy.phaseDelete.minimumAgeUnitsAriaLabel',
+        {
+          defaultMessage: 'Units for timing of delete phase',
+        }
+      );
+  }
+}
+export function getTimingLabelForPhase(phase: PhaseWithMinAgeAction) {
+  // NOTE: Hot phase isn't necessary, because indices begin in the hot phase.
+  switch (phase) {
+    case 'warm':
+      return i18n.translate('xpack.indexLifecycleMgmt.editPolicy.phaseWarm.minimumAgeLabel', {
+        defaultMessage: 'Timing for warm phase',
+      });
+
+    case 'cold':
+      return i18n.translate('xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeLabel', {
+        defaultMessage: 'Timing for cold phase',
+      });
+
+    case 'delete':
+      return i18n.translate('xpack.indexLifecycleMgmt.editPolicy.phaseDelete.minimumAgeLabel', {
+        defaultMessage: 'Timing for delete phase',
+      });
+  }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase.tsx
deleted file mode 100644
index d0aaec367104e..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase.tsx
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import React, { Fragment, FunctionComponent } from 'react';
-import { get } from 'lodash';
-import { FormattedMessage } from '@kbn/i18n/react';
-import { i18n } from '@kbn/i18n';
-import {
-  EuiTextColor,
-  EuiFlexGroup,
-  EuiFlexItem,
-  EuiSpacer,
-  EuiFormRow,
-  EuiFieldNumber,
-  EuiSwitch,
-  EuiDescribedFormGroup,
-} from '@elastic/eui';
-
-import { useFormData } from '../../../../../shared_imports';
-import { Phases, WarmPhase as WarmPhaseInterface } from '../../../../../../common/types';
-import { PhaseValidationErrors } from '../../../../services/policies/policy_validation';
-
-import { useRolloverPath } from './shared';
-
-import {
-  LearnMoreLink,
-  ActiveBadge,
-  PhaseErrorMessage,
-  OptionalLabel,
-  ErrableFormRow,
-  SetPriorityInput,
-  MinAgeInput,
-  DescribedFormField,
-  Forcemerge,
-} from '../';
-
-import { DataTierAllocationField } from './shared';
-
-const i18nTexts = {
-  shrinkLabel: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.shrinkIndexLabel', {
-    defaultMessage: 'Shrink index',
-  }),
-  moveToWarmPhaseOnRolloverLabel: i18n.translate(
-    'xpack.indexLifecycleMgmt.warmPhase.moveToWarmPhaseOnRolloverLabel',
-    {
-      defaultMessage: 'Move to warm phase on rollover',
-    }
-  ),
-  dataTierAllocation: {
-    description: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.dataTier.description', {
-      defaultMessage: 'Move data to nodes optimized for less-frequent, read-only access.',
-    }),
-  },
-};
-
-const warmProperty: keyof Phases = 'warm';
-const phaseProperty = (propertyName: keyof WarmPhaseInterface) => propertyName;
-
-interface Props {
-  setPhaseData: (
-    key: keyof WarmPhaseInterface & string,
-    value: boolean | string | undefined
-  ) => void;
-  phaseData: WarmPhaseInterface;
-  isShowingErrors: boolean;
-  errors?: PhaseValidationErrors<WarmPhaseInterface>;
-}
-export const WarmPhase: FunctionComponent<Props> = ({
-  setPhaseData,
-  phaseData,
-  errors,
-  isShowingErrors,
-}) => {
-  const [formData] = useFormData({
-    watch: useRolloverPath,
-  });
-
-  const hotPhaseRolloverEnabled = get(formData, useRolloverPath);
-
-  return (
-    <div id="warmPhaseContent" aria-live="polite" role="region" aria-relevant="additions">
-      <>
-        <EuiDescribedFormGroup
-          title={
-            <div>
-              <h2 className="eui-displayInlineBlock eui-alignMiddle">
-                <FormattedMessage
-                  id="xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseLabel"
-                  defaultMessage="Warm phase"
-                />
-              </h2>{' '}
-              {phaseData.phaseEnabled && !isShowingErrors ? <ActiveBadge /> : null}
-              <PhaseErrorMessage isShowingErrors={isShowingErrors} />
-            </div>
-          }
-          titleSize="s"
-          description={
-            <Fragment>
-              <p>
-                <FormattedMessage
-                  id="xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseDescriptionMessage"
-                  defaultMessage="You are still querying your index, but it is read-only.
-                    You can allocate shards to less performant hardware.
-                    For faster searches, you can reduce the number of shards and force merge segments."
-                />
-              </p>
-              <EuiSwitch
-                data-test-subj="enablePhaseSwitch-warm"
-                label={
-                  <FormattedMessage
-                    id="xpack.indexLifecycleMgmt.editPolicy.warmPhase.activateWarmPhaseSwitchLabel"
-                    defaultMessage="Activate warm phase"
-                  />
-                }
-                id={`${warmProperty}-${phaseProperty('phaseEnabled')}`}
-                checked={phaseData.phaseEnabled}
-                onChange={(e) => {
-                  setPhaseData(phaseProperty('phaseEnabled'), e.target.checked);
-                }}
-                aria-controls="warmPhaseContent"
-              />
-            </Fragment>
-          }
-          fullWidth
-        >
-          <Fragment>
-            {phaseData.phaseEnabled ? (
-              <Fragment>
-                {hotPhaseRolloverEnabled ? (
-                  <EuiFormRow id={`${warmProperty}-${phaseProperty('warmPhaseOnRollover')}`}>
-                    <EuiSwitch
-                      data-test-subj="warmPhaseOnRolloverSwitch"
-                      label={i18nTexts.moveToWarmPhaseOnRolloverLabel}
-                      id={`${warmProperty}-${phaseProperty('warmPhaseOnRollover')}`}
-                      checked={phaseData.warmPhaseOnRollover}
-                      onChange={(e) => {
-                        setPhaseData(phaseProperty('warmPhaseOnRollover'), e.target.checked);
-                      }}
-                    />
-                  </EuiFormRow>
-                ) : null}
-                {!phaseData.warmPhaseOnRollover || !hotPhaseRolloverEnabled ? (
-                  <Fragment>
-                    <EuiSpacer size="m" />
-                    <MinAgeInput<WarmPhaseInterface>
-                      errors={errors}
-                      phaseData={phaseData}
-                      phase={warmProperty}
-                      isShowingErrors={isShowingErrors}
-                      setPhaseData={setPhaseData}
-                      rolloverEnabled={hotPhaseRolloverEnabled}
-                    />
-                  </Fragment>
-                ) : null}
-              </Fragment>
-            ) : null}
-          </Fragment>
-        </EuiDescribedFormGroup>
-
-        {phaseData.phaseEnabled ? (
-          <Fragment>
-            {/* Data tier allocation section */}
-            <DataTierAllocationField
-              description={i18nTexts.dataTierAllocation.description}
-              phase={warmProperty}
-              setPhaseData={setPhaseData}
-              isShowingErrors={isShowingErrors}
-              phaseData={phaseData}
-            />
-
-            <DescribedFormField
-              title={
-                <h3>
-                  {i18n.translate('xpack.indexLifecycleMgmt.warmPhase.replicasTitle', {
-                    defaultMessage: 'Replicas',
-                  })}
-                </h3>
-              }
-              description={i18n.translate(
-                'xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasDescription',
-                {
-                  defaultMessage:
-                    'Set the number of replicas. Remains the same as the previous phase by default.',
-                }
-              )}
-              switchProps={{
-                label: i18n.translate(
-                  'xpack.indexLifecycleMgmt.editPolicy.warmPhase.numberOfReplicas.switchLabel',
-                  { defaultMessage: 'Set replicas' }
-                ),
-                initialValue: Boolean(phaseData.selectedReplicaCount),
-                onChange: (v) => {
-                  if (!v) {
-                    setPhaseData('selectedReplicaCount', '');
-                  }
-                },
-              }}
-              fullWidth
-            >
-              <ErrableFormRow
-                id={`${warmProperty}-${phaseProperty('selectedReplicaCount')}`}
-                label={
-                  <Fragment>
-                    <FormattedMessage
-                      id="xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasLabel"
-                      defaultMessage="Number of replicas"
-                    />
-                    <OptionalLabel />
-                  </Fragment>
-                }
-                isShowingErrors={isShowingErrors}
-                errors={errors?.selectedReplicaCount}
-              >
-                <EuiFieldNumber
-                  id={`${warmProperty}-${phaseProperty('selectedReplicaCount')}`}
-                  value={phaseData.selectedReplicaCount}
-                  onChange={(e) => {
-                    setPhaseData('selectedReplicaCount', e.target.value);
-                  }}
-                  min={0}
-                />
-              </ErrableFormRow>
-            </DescribedFormField>
-            <EuiDescribedFormGroup
-              title={
-                <h3>
-                  <FormattedMessage
-                    id="xpack.indexLifecycleMgmt.editPolicy.warmPhase.shrinkText"
-                    defaultMessage="Shrink"
-                  />
-                </h3>
-              }
-              description={
-                <EuiTextColor color="subdued">
-                  <FormattedMessage
-                    id="xpack.indexLifecycleMgmt.editPolicy.warmPhase.shrinkIndexExplanationText"
-                    defaultMessage="Shrink the index into a new index with fewer primary shards."
-                  />{' '}
-                  <LearnMoreLink docPath="indices-shrink-index.html#indices-shrink-index" />
-                </EuiTextColor>
-              }
-              fullWidth
-              titleSize="xs"
-            >
-              <Fragment>
-                <EuiSwitch
-                  data-test-subj="shrinkSwitch"
-                  checked={phaseData.shrinkEnabled}
-                  onChange={(e) => {
-                    setPhaseData(phaseProperty('shrinkEnabled'), e.target.checked);
-                  }}
-                  label={i18nTexts.shrinkLabel}
-                  aria-label={i18nTexts.shrinkLabel}
-                  aria-controls="shrinkContent"
-                />
-
-                <div id="shrinkContent" aria-live="polite" role="region">
-                  {phaseData.shrinkEnabled ? (
-                    <Fragment>
-                      <EuiSpacer />
-                      <EuiFlexGroup>
-                        <EuiFlexItem grow={false}>
-                          <ErrableFormRow
-                            id={`${warmProperty}-${phaseProperty('selectedPrimaryShardCount')}`}
-                            label={i18n.translate(
-                              'xpack.indexLifecycleMgmt.warmPhase.numberOfPrimaryShardsLabel',
-                              {
-                                defaultMessage: 'Number of primary shards',
-                              }
-                            )}
-                            isShowingErrors={isShowingErrors}
-                            errors={errors?.selectedPrimaryShardCount}
-                          >
-                            <EuiFieldNumber
-                              id={`${warmProperty}-${phaseProperty('selectedPrimaryShardCount')}`}
-                              value={phaseData.selectedPrimaryShardCount}
-                              onChange={(e) => {
-                                setPhaseData(
-                                  phaseProperty('selectedPrimaryShardCount'),
-                                  e.target.value
-                                );
-                              }}
-                              min={1}
-                            />
-                          </ErrableFormRow>
-                        </EuiFlexItem>
-                      </EuiFlexGroup>
-                      <EuiSpacer />
-                    </Fragment>
-                  ) : null}
-                </div>
-              </Fragment>
-            </EuiDescribedFormGroup>
-            <Forcemerge
-              phase={'warm'}
-              phaseData={phaseData}
-              setPhaseData={setPhaseData}
-              isShowingErrors={isShowingErrors}
-              errors={errors}
-            />
-            <SetPriorityInput<WarmPhaseInterface>
-              errors={errors}
-              phaseData={phaseData}
-              phase={warmProperty}
-              isShowingErrors={isShowingErrors}
-              setPhaseData={setPhaseData}
-            />
-          </Fragment>
-        ) : null}
-      </>
-    </div>
-  );
-};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/index.ts
new file mode 100644
index 0000000000000..d0686270ba559
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/index.ts
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { WarmPhase } from './warm_phase';
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx
new file mode 100644
index 0000000000000..7b1a4f44b5de6
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx
@@ -0,0 +1,233 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { Fragment, FunctionComponent } from 'react';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { i18n } from '@kbn/i18n';
+import { get } from 'lodash';
+
+import {
+  EuiTextColor,
+  EuiFlexGroup,
+  EuiFlexItem,
+  EuiSpacer,
+  EuiDescribedFormGroup,
+} from '@elastic/eui';
+
+import {
+  useFormData,
+  UseField,
+  ToggleField,
+  useFormContext,
+  NumericField,
+} from '../../../../../../shared_imports';
+
+import { Phases } from '../../../../../../../common/types';
+
+import { useRolloverPath, MinAgeInputField, Forcemerge, SetPriorityInput } from '../shared';
+
+import { useEditPolicyContext } from '../../../edit_policy_context';
+
+import { LearnMoreLink, ActiveBadge, PhaseErrorMessage, DescribedFormField } from '../../';
+
+import { DataTierAllocationField } from '../shared';
+
+const i18nTexts = {
+  shrinkLabel: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.shrinkIndexLabel', {
+    defaultMessage: 'Shrink index',
+  }),
+  dataTierAllocation: {
+    description: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.dataTier.description', {
+      defaultMessage: 'Move data to nodes optimized for less-frequent, read-only access.',
+    }),
+  },
+};
+
+const warmProperty: keyof Phases = 'warm';
+
+export const WarmPhase: FunctionComponent = () => {
+  const { originalPolicy } = useEditPolicyContext();
+  const form = useFormContext();
+  const [formData] = useFormData({
+    watch: [useRolloverPath, '_meta.warm.enabled', '_meta.warm.warmPhaseOnRollover'],
+  });
+
+  const enabled = get(formData, '_meta.warm.enabled');
+  const hotPhaseRolloverEnabled = get(formData, useRolloverPath);
+  const warmPhaseOnRollover = get(formData, '_meta.warm.warmPhaseOnRollover');
+  const isShowingErrors = form.isValid === false;
+
+  return (
+    <div id="warmPhaseContent" aria-live="polite" role="region" aria-relevant="additions">
+      <>
+        <EuiDescribedFormGroup
+          title={
+            <div>
+              <h2 className="eui-displayInlineBlock eui-alignMiddle">
+                <FormattedMessage
+                  id="xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseLabel"
+                  defaultMessage="Warm phase"
+                />
+              </h2>{' '}
+              {enabled && !isShowingErrors ? <ActiveBadge /> : null}
+              <PhaseErrorMessage isShowingErrors={isShowingErrors} />
+            </div>
+          }
+          titleSize="s"
+          description={
+            <Fragment>
+              <p>
+                <FormattedMessage
+                  id="xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseDescriptionMessage"
+                  defaultMessage="You are still querying your index, but it is read-only.
+                    You can allocate shards to less performant hardware.
+                    For faster searches, you can reduce the number of shards and force merge segments."
+                />
+              </p>
+              <UseField
+                path="_meta.warm.enabled"
+                component={ToggleField}
+                componentProps={{
+                  euiFieldProps: {
+                    'data-test-subj': 'enablePhaseSwitch-warm',
+                    'aria-controls': 'warmPhaseContent',
+                  },
+                }}
+              />
+            </Fragment>
+          }
+          fullWidth
+        >
+          <Fragment>
+            {enabled && (
+              <Fragment>
+                {hotPhaseRolloverEnabled && (
+                  <UseField
+                    path="_meta.warm.warmPhaseOnRollover"
+                    component={ToggleField}
+                    componentProps={{
+                      fullWidth: false,
+                      euiFieldProps: {
+                        'data-test-subj': `${warmProperty}-warmPhaseOnRollover`,
+                      },
+                    }}
+                  />
+                )}
+                {(!warmPhaseOnRollover || !hotPhaseRolloverEnabled) && (
+                  <>
+                    <EuiSpacer size="m" />
+                    <MinAgeInputField phase="warm" />
+                  </>
+                )}
+              </Fragment>
+            )}
+          </Fragment>
+        </EuiDescribedFormGroup>
+
+        {enabled && (
+          <Fragment>
+            {/* Data tier allocation section */}
+            <DataTierAllocationField
+              description={i18nTexts.dataTierAllocation.description}
+              phase={warmProperty}
+            />
+
+            <DescribedFormField
+              title={
+                <h3>
+                  {i18n.translate('xpack.indexLifecycleMgmt.warmPhase.replicasTitle', {
+                    defaultMessage: 'Replicas',
+                  })}
+                </h3>
+              }
+              description={i18n.translate(
+                'xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasDescription',
+                {
+                  defaultMessage:
+                    'Set the number of replicas. Remains the same as the previous phase by default.',
+                }
+              )}
+              switchProps={{
+                'data-test-subj': 'warm-setReplicasSwitch',
+                label: i18n.translate(
+                  'xpack.indexLifecycleMgmt.editPolicy.warmPhase.numberOfReplicas.switchLabel',
+                  { defaultMessage: 'Set replicas' }
+                ),
+                initialValue: Boolean(
+                  originalPolicy.phases.warm?.actions?.allocate?.number_of_replicas
+                ),
+              }}
+              fullWidth
+            >
+              <UseField
+                path="phases.warm.actions.allocate.number_of_replicas"
+                component={NumericField}
+                componentProps={{
+                  fullWidth: false,
+                  euiFieldProps: {
+                    'data-test-subj': `${warmProperty}-selectedReplicaCount`,
+                    min: 0,
+                  },
+                }}
+              />
+            </DescribedFormField>
+            <DescribedFormField
+              title={
+                <h3>
+                  <FormattedMessage
+                    id="xpack.indexLifecycleMgmt.editPolicy.warmPhase.shrinkText"
+                    defaultMessage="Shrink"
+                  />
+                </h3>
+              }
+              description={
+                <EuiTextColor color="subdued">
+                  <FormattedMessage
+                    id="xpack.indexLifecycleMgmt.editPolicy.warmPhase.shrinkIndexExplanationText"
+                    defaultMessage="Shrink the index into a new index with fewer primary shards."
+                  />{' '}
+                  <LearnMoreLink docPath="indices-shrink-index.html#indices-shrink-index" />
+                </EuiTextColor>
+              }
+              titleSize="xs"
+              switchProps={{
+                'aria-controls': 'shrinkContent',
+                'data-test-subj': 'shrinkSwitch',
+                label: i18nTexts.shrinkLabel,
+                'aria-label': i18nTexts.shrinkLabel,
+                initialValue: Boolean(originalPolicy.phases.warm?.actions?.shrink),
+              }}
+              fullWidth
+            >
+              <div id="shrinkContent" aria-live="polite" role="region">
+                <EuiSpacer />
+                <EuiFlexGroup>
+                  <EuiFlexItem grow={false}>
+                    <UseField
+                      path="phases.warm.actions.shrink.number_of_shards"
+                      component={NumericField}
+                      componentProps={{
+                        euiFieldProps: {
+                          'data-test-subj': `${warmProperty}-selectedPrimaryShardCount`,
+                          min: 1,
+                        },
+                      }}
+                    />
+                  </EuiFlexItem>
+                </EuiFlexGroup>
+                <EuiSpacer />
+              </div>
+            </DescribedFormField>
+
+            <Forcemerge phase="warm" />
+
+            <SetPriorityInput phase="warm" />
+          </Fragment>
+        )}
+      </>
+    </div>
+  );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/policy_json_flyout.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/policy_json_flyout.tsx
index e9ce193118b35..9ed24355ce7b3 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/policy_json_flyout.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/policy_json_flyout.tsx
@@ -4,7 +4,7 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-import React, { useEffect, useState } from 'react';
+import React, { useCallback, useEffect, useState } from 'react';
 import { i18n } from '@kbn/i18n';
 import { FormattedMessage } from '@kbn/i18n/react';
 
@@ -25,6 +25,7 @@ import {
 import { SerializedPolicy } from '../../../../../common/types';
 
 import { useFormContext, useFormData } from '../../../../shared_imports';
+import { FormInternal } from '../types';
 
 interface Props {
   legacyPolicy: SerializedPolicy;
@@ -44,27 +45,29 @@ export const PolicyJsonFlyout: React.FunctionComponent<Props> = ({
    */
   const [policy, setPolicy] = useState<undefined | null | SerializedPolicy>(undefined);
 
-  const form = useFormContext();
-  const [formData, getFormData] = useFormData();
+  const { validate: validateForm } = useFormContext();
+  const [, getFormData] = useFormData<FormInternal>();
+
+  const updatePolicy = useCallback(async () => {
+    setPolicy(undefined);
+    if (await validateForm()) {
+      const p = getFormData() as SerializedPolicy;
+      setPolicy({
+        ...legacyPolicy,
+        phases: {
+          ...legacyPolicy.phases,
+          hot: p.phases.hot,
+          warm: p.phases.warm,
+        },
+      });
+    } else {
+      setPolicy(null);
+    }
+  }, [setPolicy, getFormData, legacyPolicy, validateForm]);
 
   useEffect(() => {
-    (async function checkPolicy() {
-      setPolicy(undefined);
-      if (await form.validate()) {
-        const p = getFormData() as SerializedPolicy;
-        setPolicy({
-          ...legacyPolicy,
-          phases: {
-            ...legacyPolicy.phases,
-            hot: p.phases.hot,
-          },
-        });
-      } else {
-        setPolicy(null);
-      }
-    })();
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [form, legacyPolicy, formData]);
+    updatePolicy();
+  }, [updatePolicy]);
 
   let content: React.ReactNode;
   switch (policy) {
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/set_priority_input.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/set_priority_input_legacy.tsx
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/set_priority_input.tsx
rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/set_priority_input_legacy.tsx
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/toggleable_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/toggleable_field.tsx
index ff4301808db33..d188a172d746b 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/toggleable_field.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/toggleable_field.tsx
@@ -9,7 +9,7 @@ import { EuiSpacer, EuiSwitch, EuiSwitchProps } from '@elastic/eui';
 
 export interface Props extends Omit<EuiSwitchProps, 'checked' | 'onChange'> {
   initialValue: boolean;
-  onChange: (nextValue: boolean) => void;
+  onChange?: (nextValue: boolean) => void;
 }
 
 export const ToggleableField: FunctionComponent<Props> = ({
@@ -28,7 +28,9 @@ export const ToggleableField: FunctionComponent<Props> = ({
         onChange={(e) => {
           const nextValue = e.target.checked;
           setIsContentVisible(nextValue);
-          onChange(nextValue);
+          if (onChange) {
+            onChange(nextValue);
+          }
         }}
       />
       <EuiSpacer size="m" />
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts
index bb24eea64ec8c..760c6ad713ea0 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts
@@ -10,22 +10,32 @@ import { SerializedPolicy } from '../../../../common/types';
 
 import { splitSizeAndUnits } from '../../services/policies/policy_serialization';
 
+import { determineDataTierAllocationType } from '../../lib';
+
 import { FormInternal } from './types';
 
-export const deserializer = (policy: SerializedPolicy): FormInternal =>
-  produce<FormInternal>(
+export const deserializer = (policy: SerializedPolicy): FormInternal => {
+  const _meta: FormInternal['_meta'] = {
+    hot: {
+      useRollover: Boolean(policy.phases.hot?.actions?.rollover),
+      forceMergeEnabled: Boolean(policy.phases.hot?.actions?.forcemerge),
+      bestCompression: policy.phases.hot?.actions?.forcemerge?.index_codec === 'best_compression',
+    },
+    warm: {
+      enabled: Boolean(policy.phases.warm),
+      warmPhaseOnRollover: Boolean(policy.phases.warm?.min_age === '0ms'),
+      forceMergeEnabled: Boolean(policy.phases.warm?.actions?.forcemerge),
+      bestCompression: policy.phases.warm?.actions?.forcemerge?.index_codec === 'best_compression',
+      dataTierAllocationType: determineDataTierAllocationType(policy.phases.warm?.actions),
+    },
+  };
+
+  return produce<FormInternal>(
     {
       ...policy,
-      _meta: {
-        hot: {
-          useRollover: Boolean(policy.phases.hot?.actions?.rollover),
-          forceMergeEnabled: Boolean(policy.phases.hot?.actions?.forcemerge),
-          bestCompression:
-            policy.phases.hot?.actions?.forcemerge?.index_codec === 'best_compression',
-        },
-      },
+      _meta,
     },
-    (draft) => {
+    (draft: FormInternal) => {
       if (draft.phases.hot?.actions?.rollover) {
         if (draft.phases.hot.actions.rollover.max_size) {
           const maxSize = splitSizeAndUnits(draft.phases.hot.actions.rollover.max_size);
@@ -39,5 +49,20 @@ export const deserializer = (policy: SerializedPolicy): FormInternal =>
           draft._meta.hot.maxAgeUnit = maxAge.units;
         }
       }
+
+      if (draft.phases.warm) {
+        if (draft.phases.warm.actions?.allocate?.require) {
+          Object.entries(draft.phases.warm.actions.allocate.require).forEach((entry) => {
+            draft._meta.warm.allocationNodeAttribute = entry.join(':');
+          });
+        }
+
+        if (draft.phases.warm.min_age) {
+          const minAge = splitSizeAndUnits(draft.phases.warm.min_age);
+          draft.phases.warm.min_age = minAge.size;
+          draft._meta.warm.minAgeUnit = minAge.units;
+        }
+      }
     }
   );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx
index 8f8b0447f378a..eecdfb4871a67 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx
@@ -67,6 +67,8 @@ import { schema } from './form_schema';
 import { deserializer } from './deserializer';
 import { createSerializer } from './serializer';
 
+import { EditPolicyContextProvider } from './edit_policy_context';
+
 export interface Props {
   policies: PolicyFromES[];
   policyName: string;
@@ -89,6 +91,7 @@ const mergeAllSerializedPolicies = (
     phases: {
       ...legacySerializedPolicy.phases,
       hot: serializedPolicy.phases.hot,
+      warm: serializedPolicy.phases.warm,
     },
   };
 };
@@ -113,9 +116,11 @@ export const EditPolicy: React.FunctionComponent<Props> = ({
     return createSerializer(existingPolicy?.policy);
   }, [existingPolicy?.policy]);
 
+  const originalPolicy = existingPolicy?.policy ?? defaultPolicy;
+
   const { form } = useForm({
     schema,
-    defaultValue: existingPolicy?.policy ?? defaultPolicy,
+    defaultValue: originalPolicy,
     deserializer,
     serializer,
   });
@@ -132,22 +137,6 @@ export const EditPolicy: React.FunctionComponent<Props> = ({
     history.push('/policies');
   };
 
-  const setWarmPhaseOnRollover = useCallback(
-    (value: boolean) => {
-      setPolicy((p) => ({
-        ...p,
-        phases: {
-          ...p.phases,
-          warm: {
-            ...p.phases.warm,
-            warmPhaseOnRollover: value,
-          },
-        },
-      }));
-    },
-    [setPolicy]
-  );
-
   const submit = async () => {
     setIsShowingErrors(true);
     const { data: formLibPolicy, isValid: newIsValid } = await form.submit();
@@ -206,10 +195,6 @@ export const EditPolicy: React.FunctionComponent<Props> = ({
     [setPolicy]
   );
 
-  const setWarmPhaseData = useCallback(
-    (key: string, value: any) => setPhaseData('warm', key, value),
-    [setPhaseData]
-  );
   const setColdPhaseData = useCallback(
     (key: string, value: any) => setPhaseData('cold', key, value),
     [setPhaseData]
@@ -220,234 +205,236 @@ export const EditPolicy: React.FunctionComponent<Props> = ({
   );
 
   return (
-    <EuiPage>
-      <EuiPageBody>
-        <EuiPageContent
-          className="ilmEditPolicyPageContent"
-          verticalPosition="center"
-          horizontalPosition="center"
-        >
-          <EuiTitle size="l">
-            <h1>
-              {isNewPolicy
-                ? i18n.translate('xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage', {
-                    defaultMessage: 'Create an index lifecycle policy',
-                  })
-                : i18n.translate('xpack.indexLifecycleMgmt.editPolicy.editPolicyMessage', {
-                    defaultMessage: 'Edit index lifecycle policy {originalPolicyName}',
-                    values: { originalPolicyName },
-                  })}
-            </h1>
-          </EuiTitle>
-
-          <div className="euiAnimateContentLoad">
-            <Form form={form}>
-              <EuiSpacer size="xs" />
-              <EuiText color="subdued">
-                <p>
-                  <FormattedMessage
-                    id="xpack.indexLifecycleMgmt.editPolicy.lifecyclePolicyDescriptionText"
-                    defaultMessage="Use an index policy to automate the four phases of the index lifecycle,
+    <EditPolicyContextProvider value={{ originalPolicy }}>
+      <EuiPage>
+        <EuiPageBody>
+          <EuiPageContent
+            className="ilmEditPolicyPageContent"
+            verticalPosition="center"
+            horizontalPosition="center"
+          >
+            <EuiTitle size="l">
+              <h1>
+                {isNewPolicy
+                  ? i18n.translate('xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage', {
+                      defaultMessage: 'Create an index lifecycle policy',
+                    })
+                  : i18n.translate('xpack.indexLifecycleMgmt.editPolicy.editPolicyMessage', {
+                      defaultMessage: 'Edit index lifecycle policy {originalPolicyName}',
+                      values: { originalPolicyName },
+                    })}
+              </h1>
+            </EuiTitle>
+
+            <div className="euiAnimateContentLoad">
+              <Form form={form}>
+                <EuiSpacer size="xs" />
+                <EuiText color="subdued">
+                  <p>
+                    <FormattedMessage
+                      id="xpack.indexLifecycleMgmt.editPolicy.lifecyclePolicyDescriptionText"
+                      defaultMessage="Use an index policy to automate the four phases of the index lifecycle,
                       from actively writing to the index to deleting it."
-                  />{' '}
-                  <LearnMoreLink
-                    docPath="index-lifecycle-management.html"
-                    text={
-                      <FormattedMessage
-                        id="xpack.indexLifecycleMgmt.editPolicy.learnAboutIndexLifecycleManagementLinkText"
-                        defaultMessage="Learn about the index lifecycle."
-                      />
-                    }
-                  />
-                </p>
-              </EuiText>
+                    />{' '}
+                    <LearnMoreLink
+                      docPath="index-lifecycle-management.html"
+                      text={
+                        <FormattedMessage
+                          id="xpack.indexLifecycleMgmt.editPolicy.learnAboutIndexLifecycleManagementLinkText"
+                          defaultMessage="Learn about the index lifecycle."
+                        />
+                      }
+                    />
+                  </p>
+                </EuiText>
 
-              <EuiSpacer />
+                <EuiSpacer />
 
-              {isNewPolicy ? null : (
-                <Fragment>
-                  <EuiText>
-                    <p>
-                      <strong>
+                {isNewPolicy ? null : (
+                  <Fragment>
+                    <EuiText>
+                      <p>
+                        <strong>
+                          <FormattedMessage
+                            id="xpack.indexLifecycleMgmt.editPolicy.editingExistingPolicyMessage"
+                            defaultMessage="You are editing an existing policy"
+                          />
+                        </strong>
+                        .{' '}
                         <FormattedMessage
-                          id="xpack.indexLifecycleMgmt.editPolicy.editingExistingPolicyMessage"
-                          defaultMessage="You are editing an existing policy"
-                        />
-                      </strong>
-                      .{' '}
-                      <FormattedMessage
-                        id="xpack.indexLifecycleMgmt.editPolicy.editingExistingPolicyExplanationMessage"
-                        defaultMessage="Any changes you make will affect the indices that are
+                          id="xpack.indexLifecycleMgmt.editPolicy.editingExistingPolicyExplanationMessage"
+                          defaultMessage="Any changes you make will affect the indices that are
                               attached to this policy. Alternatively, you can save these changes in
                               a new policy."
+                        />
+                      </p>
+                    </EuiText>
+                    <EuiSpacer />
+
+                    <EuiFormRow>
+                      <EuiSwitch
+                        data-test-subj="saveAsNewSwitch"
+                        style={{ maxWidth: '100%' }}
+                        checked={saveAsNew}
+                        onChange={(e) => {
+                          setSaveAsNew(e.target.checked);
+                        }}
+                        label={
+                          <span>
+                            <FormattedMessage
+                              id="xpack.indexLifecycleMgmt.editPolicy.saveAsNewPolicyMessage"
+                              defaultMessage="Save as new policy"
+                            />
+                          </span>
+                        }
                       />
-                    </p>
-                  </EuiText>
-                  <EuiSpacer />
-
-                  <EuiFormRow>
-                    <EuiSwitch
-                      data-test-subj="saveAsNewSwitch"
-                      style={{ maxWidth: '100%' }}
-                      checked={saveAsNew}
-                      onChange={(e) => {
-                        setSaveAsNew(e.target.checked);
-                      }}
-                      label={
-                        <span>
+                    </EuiFormRow>
+                  </Fragment>
+                )}
+
+                {saveAsNew || isNewPolicy ? (
+                  <EuiDescribedFormGroup
+                    title={
+                      <div>
+                        <span className="eui-displayInlineBlock eui-alignMiddle">
                           <FormattedMessage
-                            id="xpack.indexLifecycleMgmt.editPolicy.saveAsNewPolicyMessage"
-                            defaultMessage="Save as new policy"
+                            id="xpack.indexLifecycleMgmt.editPolicy.nameLabel"
+                            defaultMessage="Name"
                           />
                         </span>
-                      }
-                    />
-                  </EuiFormRow>
-                </Fragment>
-              )}
-
-              {saveAsNew || isNewPolicy ? (
-                <EuiDescribedFormGroup
-                  title={
-                    <div>
-                      <span className="eui-displayInlineBlock eui-alignMiddle">
+                      </div>
+                    }
+                    titleSize="s"
+                    fullWidth
+                  >
+                    <ErrableFormRow
+                      id={'policyName'}
+                      label={i18n.translate('xpack.indexLifecycleMgmt.editPolicy.policyNameLabel', {
+                        defaultMessage: 'Policy name',
+                      })}
+                      isShowingErrors={isShowingErrors}
+                      errors={errors?.policyName}
+                      helpText={
                         <FormattedMessage
-                          id="xpack.indexLifecycleMgmt.editPolicy.nameLabel"
-                          defaultMessage="Name"
+                          id="xpack.indexLifecycleMgmt.editPolicy.validPolicyNameMessage"
+                          defaultMessage="A policy name cannot start with an underscore and cannot contain a question mark or a space."
                         />
-                      </span>
-                    </div>
-                  }
-                  titleSize="s"
-                  fullWidth
-                >
-                  <ErrableFormRow
-                    id={'policyName'}
-                    label={i18n.translate('xpack.indexLifecycleMgmt.editPolicy.policyNameLabel', {
-                      defaultMessage: 'Policy name',
-                    })}
-                    isShowingErrors={isShowingErrors}
-                    errors={errors?.policyName}
-                    helpText={
-                      <FormattedMessage
-                        id="xpack.indexLifecycleMgmt.editPolicy.validPolicyNameMessage"
-                        defaultMessage="A policy name cannot start with an underscore and cannot contain a question mark or a space."
+                      }
+                    >
+                      <EuiFieldText
+                        data-test-subj="policyNameField"
+                        value={policy.name}
+                        onChange={(e) => {
+                          setPolicy({ ...policy, name: e.target.value });
+                        }}
                       />
-                    }
-                  >
-                    <EuiFieldText
-                      data-test-subj="policyNameField"
-                      value={policy.name}
-                      onChange={(e) => {
-                        setPolicy({ ...policy, name: e.target.value });
-                      }}
-                    />
-                  </ErrableFormRow>
-                </EuiDescribedFormGroup>
-              ) : null}
-
-              <EuiSpacer />
-
-              <HotPhase setWarmPhaseOnRollover={setWarmPhaseOnRollover} />
-
-              <EuiHorizontalRule />
-
-              <WarmPhase
-                errors={errors?.warm}
-                isShowingErrors={isShowingErrors && !!errors && Object.keys(errors.warm).length > 0}
-                setPhaseData={setWarmPhaseData}
-                phaseData={policy.phases.warm}
-              />
-
-              <EuiHorizontalRule />
-
-              <ColdPhase
-                errors={errors?.cold}
-                isShowingErrors={isShowingErrors && !!errors && Object.keys(errors.cold).length > 0}
-                setPhaseData={setColdPhaseData}
-                phaseData={policy.phases.cold}
-              />
-
-              <EuiHorizontalRule />
-
-              <DeletePhase
-                errors={errors?.delete}
-                isShowingErrors={
-                  isShowingErrors && !!errors && Object.keys(errors.delete).length > 0
-                }
-                getUrlForApp={getUrlForApp}
-                setPhaseData={setDeletePhaseData}
-                phaseData={policy.phases.delete}
-              />
-
-              <EuiHorizontalRule />
-
-              <EuiFlexGroup justifyContent="spaceBetween">
-                <EuiFlexItem grow={false}>
-                  <EuiFlexGroup>
-                    <EuiFlexItem grow={false}>
-                      <EuiButton
-                        data-test-subj="savePolicyButton"
-                        fill
-                        iconType="check"
-                        iconSide="left"
-                        disabled={form.isValid === false || form.isSubmitting}
-                        onClick={submit}
-                        color="secondary"
-                      >
-                        {saveAsNew ? (
-                          <FormattedMessage
-                            id="xpack.indexLifecycleMgmt.editPolicy.saveAsNewButton"
-                            defaultMessage="Save as new policy"
-                          />
-                        ) : (
+                    </ErrableFormRow>
+                  </EuiDescribedFormGroup>
+                ) : null}
+
+                <EuiSpacer />
+
+                <HotPhase />
+
+                <EuiHorizontalRule />
+
+                <WarmPhase />
+
+                <EuiHorizontalRule />
+
+                <ColdPhase
+                  errors={errors?.cold}
+                  isShowingErrors={
+                    isShowingErrors && !!errors && Object.keys(errors.cold).length > 0
+                  }
+                  setPhaseData={setColdPhaseData}
+                  phaseData={policy.phases.cold}
+                />
+
+                <EuiHorizontalRule />
+
+                <DeletePhase
+                  errors={errors?.delete}
+                  isShowingErrors={
+                    isShowingErrors && !!errors && Object.keys(errors.delete).length > 0
+                  }
+                  getUrlForApp={getUrlForApp}
+                  setPhaseData={setDeletePhaseData}
+                  phaseData={policy.phases.delete}
+                />
+
+                <EuiHorizontalRule />
+
+                <EuiFlexGroup justifyContent="spaceBetween">
+                  <EuiFlexItem grow={false}>
+                    <EuiFlexGroup>
+                      <EuiFlexItem grow={false}>
+                        <EuiButton
+                          data-test-subj="savePolicyButton"
+                          fill
+                          iconType="check"
+                          iconSide="left"
+                          disabled={form.isValid === false || form.isSubmitting}
+                          onClick={submit}
+                          color="secondary"
+                        >
+                          {saveAsNew ? (
+                            <FormattedMessage
+                              id="xpack.indexLifecycleMgmt.editPolicy.saveAsNewButton"
+                              defaultMessage="Save as new policy"
+                            />
+                          ) : (
+                            <FormattedMessage
+                              id="xpack.indexLifecycleMgmt.editPolicy.saveButton"
+                              defaultMessage="Save policy"
+                            />
+                          )}
+                        </EuiButton>
+                      </EuiFlexItem>
+
+                      <EuiFlexItem grow={false}>
+                        <EuiButtonEmpty
+                          data-test-subj="cancelTestPolicy"
+                          onClick={backToPolicyList}
+                        >
                           <FormattedMessage
-                            id="xpack.indexLifecycleMgmt.editPolicy.saveButton"
-                            defaultMessage="Save policy"
+                            id="xpack.indexLifecycleMgmt.editPolicy.cancelButton"
+                            defaultMessage="Cancel"
                           />
-                        )}
-                      </EuiButton>
-                    </EuiFlexItem>
-
-                    <EuiFlexItem grow={false}>
-                      <EuiButtonEmpty data-test-subj="cancelTestPolicy" onClick={backToPolicyList}>
+                        </EuiButtonEmpty>
+                      </EuiFlexItem>
+                    </EuiFlexGroup>
+                  </EuiFlexItem>
+
+                  <EuiFlexItem grow={false}>
+                    <EuiButtonEmpty onClick={togglePolicyJsonFlyout} data-test-subj="requestButton">
+                      {isShowingPolicyJsonFlyout ? (
                         <FormattedMessage
-                          id="xpack.indexLifecycleMgmt.editPolicy.cancelButton"
-                          defaultMessage="Cancel"
+                          id="xpack.indexLifecycleMgmt.editPolicy.hidePolicyJsonButto"
+                          defaultMessage="Hide request"
                         />
-                      </EuiButtonEmpty>
-                    </EuiFlexItem>
-                  </EuiFlexGroup>
-                </EuiFlexItem>
-
-                <EuiFlexItem grow={false}>
-                  <EuiButtonEmpty onClick={togglePolicyJsonFlyout} data-test-subj="requestButton">
-                    {isShowingPolicyJsonFlyout ? (
-                      <FormattedMessage
-                        id="xpack.indexLifecycleMgmt.editPolicy.hidePolicyJsonButto"
-                        defaultMessage="Hide request"
-                      />
-                    ) : (
-                      <FormattedMessage
-                        id="xpack.indexLifecycleMgmt.editPolicy.showPolicyJsonButto"
-                        defaultMessage="Show request"
-                      />
-                    )}
-                  </EuiButtonEmpty>
-                </EuiFlexItem>
-              </EuiFlexGroup>
-
-              {isShowingPolicyJsonFlyout ? (
-                <PolicyJsonFlyout
-                  policyName={policy.name || ''}
-                  legacyPolicy={legacySerializePolicy(policy, existingPolicy?.policy)}
-                  close={() => setIsShowingPolicyJsonFlyout(false)}
-                />
-              ) : null}
-            </Form>
-          </div>
-        </EuiPageContent>
-      </EuiPageBody>
-    </EuiPage>
+                      ) : (
+                        <FormattedMessage
+                          id="xpack.indexLifecycleMgmt.editPolicy.showPolicyJsonButto"
+                          defaultMessage="Show request"
+                        />
+                      )}
+                    </EuiButtonEmpty>
+                  </EuiFlexItem>
+                </EuiFlexGroup>
+
+                {isShowingPolicyJsonFlyout ? (
+                  <PolicyJsonFlyout
+                    policyName={policy.name || ''}
+                    legacyPolicy={legacySerializePolicy(policy, existingPolicy?.policy)}
+                    close={() => setIsShowingPolicyJsonFlyout(false)}
+                  />
+                ) : null}
+              </Form>
+            </div>
+          </EuiPageContent>
+        </EuiPageBody>
+      </EuiPage>
+    </EditPolicyContextProvider>
   );
 };
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx
new file mode 100644
index 0000000000000..4748c26d6cec1
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx
@@ -0,0 +1,32 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { createContext, ReactChild, useContext } from 'react';
+import { SerializedPolicy } from '../../../../common/types';
+
+interface EditPolicyContextValue {
+  originalPolicy: SerializedPolicy;
+}
+
+const EditPolicyContext = createContext<EditPolicyContextValue>(null as any);
+
+export const EditPolicyContextProvider = ({
+  value,
+  children,
+}: {
+  value: EditPolicyContextValue;
+  children: ReactChild;
+}) => {
+  return <EditPolicyContext.Provider value={value}>{children}</EditPolicyContext.Provider>;
+};
+
+export const useEditPolicyContext = () => {
+  const ctx = useContext(EditPolicyContext);
+  if (!ctx) {
+    throw new Error('useEditPolicyContext can only be called inside of EditPolicyContext!');
+  }
+  return ctx;
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts
index 806164c8b0da1..a80382e87539c 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts
@@ -7,13 +7,19 @@
 import { i18n } from '@kbn/i18n';
 
 import { FormSchema, fieldValidators } from '../../../shared_imports';
-import { defaultSetPriority } from '../../constants';
+import { defaultSetPriority, defaultPhaseIndexPriority } from '../../constants';
 
 import { FormInternal } from './types';
+
 import { ifExistsNumberGreaterThanZero, rolloverThresholdsValidator } from './form_validations';
+
 import { i18nTexts } from './i18n_texts';
 
-const { emptyField } = fieldValidators;
+const { emptyField, numberGreaterThanField } = fieldValidators;
+
+const serializers = {
+  stringToNumber: (v: string): any => (v ? parseInt(v, 10) : undefined),
+};
 
 export const schema: FormSchema<FormInternal> = {
   _meta: {
@@ -30,21 +36,38 @@ export const schema: FormSchema<FormInternal> = {
       maxAgeUnit: {
         defaultValue: 'd',
       },
-      forceMergeEnabled: {
-        label: i18nTexts.editPolicy.forceMergeEnabledFieldLabel,
-      },
       bestCompression: {
-        label: i18n.translate('xpack.indexLifecycleMgmt.forcemerge.bestCompressionLabel', {
-          defaultMessage: 'Compress stored fields',
-        }),
-        helpText: i18n.translate(
-          'xpack.indexLifecycleMgmt.editPolicy.forceMerge.bestCompressionText',
-          {
-            defaultMessage:
-              'Use higher compression for stored fields at the cost of slower performance.',
-          }
+        label: i18nTexts.editPolicy.bestCompressionFieldLabel,
+        helpText: i18nTexts.editPolicy.bestCompressionFieldHelpText,
+      },
+    },
+    warm: {
+      enabled: {
+        defaultValue: false,
+        label: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.warmPhase.activateWarmPhaseSwitchLabel',
+          { defaultMessage: 'Activate warm phase' }
         ),
       },
+      warmPhaseOnRollover: {
+        defaultValue: true,
+        label: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.moveToWarmPhaseOnRolloverLabel', {
+          defaultMessage: 'Move to warm phase on rollover',
+        }),
+      },
+      minAgeUnit: {
+        defaultValue: 'ms',
+      },
+      bestCompression: {
+        label: i18nTexts.editPolicy.bestCompressionFieldLabel,
+        helpText: i18nTexts.editPolicy.bestCompressionFieldHelpText,
+      },
+      dataTierAllocationType: {
+        label: i18nTexts.editPolicy.allocationTypeOptionsFieldLabel,
+      },
+      allocationNodeAttribute: {
+        label: i18nTexts.editPolicy.allocationNodeAttributeFieldLabel,
+      },
     },
   },
   phases: {
@@ -76,7 +99,7 @@ export const schema: FormSchema<FormInternal> = {
                 validator: ifExistsNumberGreaterThanZero,
               },
             ],
-            serializer: (v: string): any => (v ? parseInt(v, 10) : undefined),
+            serializer: serializers.stringToNumber,
           },
           max_size: {
             label: i18n.translate('xpack.indexLifecycleMgmt.hotPhase.maximumIndexSizeLabel', {
@@ -94,9 +117,7 @@ export const schema: FormSchema<FormInternal> = {
         },
         forcemerge: {
           max_num_segments: {
-            label: i18n.translate('xpack.indexLifecycleMgmt.forceMerge.numberOfSegmentsLabel', {
-              defaultMessage: 'Number of segments',
-            }),
+            label: i18nTexts.editPolicy.maxNumSegmentsFieldLabel,
             validations: [
               {
                 validator: emptyField(
@@ -110,17 +131,94 @@ export const schema: FormSchema<FormInternal> = {
                 validator: ifExistsNumberGreaterThanZero,
               },
             ],
-            serializer: (v: string): any => (v ? parseInt(v, 10) : undefined),
+            serializer: serializers.stringToNumber,
           },
         },
         set_priority: {
           priority: {
             defaultValue: defaultSetPriority as any,
-            label: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.indexPriorityLabel', {
-              defaultMessage: 'Index priority (optional)',
+            label: i18nTexts.editPolicy.setPriorityFieldLabel,
+            validations: [{ validator: ifExistsNumberGreaterThanZero }],
+            serializer: serializers.stringToNumber,
+          },
+        },
+      },
+    },
+    warm: {
+      min_age: {
+        defaultValue: '0',
+        validations: [
+          {
+            validator: (arg) =>
+              numberGreaterThanField({
+                than: 0,
+                allowEquality: true,
+                message: i18nTexts.editPolicy.errors.nonNegativeNumberRequired,
+              })({
+                ...arg,
+                value: arg.value === '' ? -Infinity : parseInt(arg.value, 10),
+              }),
+          },
+        ],
+      },
+      actions: {
+        allocate: {
+          number_of_replicas: {
+            label: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasLabel', {
+              defaultMessage: 'Number of replicas (optional)',
+            }),
+            validations: [
+              {
+                validator: ifExistsNumberGreaterThanZero,
+              },
+            ],
+            serializer: serializers.stringToNumber,
+          },
+        },
+        shrink: {
+          number_of_shards: {
+            label: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.numberOfPrimaryShardsLabel', {
+              defaultMessage: 'Number of primary shards',
             }),
+            validations: [
+              {
+                validator: emptyField(i18nTexts.editPolicy.errors.numberRequired),
+              },
+              {
+                validator: numberGreaterThanField({
+                  message: i18nTexts.editPolicy.errors.numberGreatThan0Required,
+                  than: 0,
+                }),
+              },
+            ],
+            serializer: serializers.stringToNumber,
+          },
+        },
+        forcemerge: {
+          max_num_segments: {
+            label: i18nTexts.editPolicy.maxNumSegmentsFieldLabel,
+            validations: [
+              {
+                validator: emptyField(
+                  i18n.translate(
+                    'xpack.indexLifecycleMgmt.editPolicy.forcemerge.numberOfSegmentsRequiredError',
+                    { defaultMessage: 'A value for number of segments is required.' }
+                  )
+                ),
+              },
+              {
+                validator: ifExistsNumberGreaterThanZero,
+              },
+            ],
+            serializer: serializers.stringToNumber,
+          },
+        },
+        set_priority: {
+          priority: {
+            defaultValue: defaultPhaseIndexPriority as any,
+            label: i18nTexts.editPolicy.setPriorityFieldLabel,
             validations: [{ validator: ifExistsNumberGreaterThanZero }],
-            serializer: (v: string): any => (v ? parseInt(v, 10) : undefined),
+            serializer: serializers.stringToNumber,
           },
         },
       },
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts
index b937ea2043138..37ca4e9def340 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts
@@ -4,27 +4,19 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-import { i18n } from '@kbn/i18n';
 import { fieldValidators, ValidationFunc } from '../../../shared_imports';
 
-import { i18nTexts } from './components/phases/hot_phase/i18n_texts';
-
 import { ROLLOVER_FORM_PATHS } from './constants';
 
-const { numberGreaterThanField } = fieldValidators;
+import { i18nTexts } from './i18n_texts';
 
-export const positiveNumberRequiredMessage = i18n.translate(
-  'xpack.indexLifecycleMgmt.editPolicy.numberAboveZeroRequiredError',
-  {
-    defaultMessage: 'Only numbers above 0 are allowed.',
-  }
-);
+const { numberGreaterThanField } = fieldValidators;
 
 export const ifExistsNumberGreaterThanZero: ValidationFunc<any, any, any> = (arg) => {
   if (arg.value) {
     return numberGreaterThanField({
       than: 0,
-      message: positiveNumberRequiredMessage,
+      message: i18nTexts.editPolicy.errors.numberGreatThan0Required,
     })({
       ...arg,
       value: parseInt(arg.value, 10),
@@ -54,16 +46,22 @@ export const rolloverThresholdsValidator: ValidationFunc = ({ form }) => {
     )
   ) {
     fields[ROLLOVER_FORM_PATHS.maxAge].setErrors([
-      { validationType: ROLLOVER_EMPTY_VALIDATION, message: i18nTexts.maximumAgeRequiredMessage },
+      {
+        validationType: ROLLOVER_EMPTY_VALIDATION,
+        message: i18nTexts.editPolicy.errors.maximumAgeRequiredMessage,
+      },
     ]);
     fields[ROLLOVER_FORM_PATHS.maxDocs].setErrors([
       {
         validationType: ROLLOVER_EMPTY_VALIDATION,
-        message: i18nTexts.maximumDocumentsRequiredMessage,
+        message: i18nTexts.editPolicy.errors.maximumDocumentsRequiredMessage,
       },
     ]);
     fields[ROLLOVER_FORM_PATHS.maxSize].setErrors([
-      { validationType: ROLLOVER_EMPTY_VALIDATION, message: i18nTexts.maximumSizeRequiredMessage },
+      {
+        validationType: ROLLOVER_EMPTY_VALIDATION,
+        message: i18nTexts.editPolicy.errors.maximumSizeRequiredMessage,
+      },
     ]);
   } else {
     fields[ROLLOVER_FORM_PATHS.maxAge].clearErrors(ROLLOVER_EMPTY_VALIDATION);
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts
index 31bb10b402d27..1fba69b7634ae 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts
@@ -11,5 +11,93 @@ export const i18nTexts = {
     forceMergeEnabledFieldLabel: i18n.translate('xpack.indexLifecycleMgmt.forcemerge.enableLabel', {
       defaultMessage: 'Force merge data',
     }),
+    maxNumSegmentsFieldLabel: i18n.translate(
+      'xpack.indexLifecycleMgmt.forceMerge.numberOfSegmentsLabel',
+      {
+        defaultMessage: 'Number of segments',
+      }
+    ),
+    setPriorityFieldLabel: i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.indexPriorityLabel',
+      {
+        defaultMessage: 'Index priority (optional)',
+      }
+    ),
+    bestCompressionFieldLabel: i18n.translate(
+      'xpack.indexLifecycleMgmt.forcemerge.bestCompressionLabel',
+      {
+        defaultMessage: 'Compress stored fields',
+      }
+    ),
+    bestCompressionFieldHelpText: i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.forceMerge.bestCompressionText',
+      {
+        defaultMessage:
+          'Use higher compression for stored fields at the cost of slower performance.',
+      }
+    ),
+    allocationTypeOptionsFieldLabel: i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.dataTierAllocation.allocationFieldLabel',
+      { defaultMessage: 'Data tier options' }
+    ),
+    allocationNodeAttributeFieldLabel: i18n.translate(
+      'xpack.indexLifecycleMgmt.editPolicy.dataTierAllocation.nodeAllocationFieldLabel',
+      {
+        defaultMessage: 'Select a node attribute',
+      }
+    ),
+    errors: {
+      numberRequired: i18n.translate(
+        'xpack.indexLifecycleMgmt.editPolicy.errors.numberRequiredErrorMessage',
+        {
+          defaultMessage: 'A number is required.',
+        }
+      ),
+      numberGreatThan0Required: i18n.translate(
+        'xpack.indexLifecycleMgmt.editPolicy.errors.numberAboveZeroRequiredError',
+        {
+          defaultMessage: 'Only numbers above 0 are allowed.',
+        }
+      ),
+      maximumAgeRequiredMessage: i18n.translate(
+        'xpack.indexLifecycleMgmt.editPolicy.errors.maximumAgeMissingError',
+        {
+          defaultMessage: 'A maximum age is required.',
+        }
+      ),
+      maximumSizeRequiredMessage: i18n.translate(
+        'xpack.indexLifecycleMgmt.editPolicy.errors.maximumIndexSizeMissingError',
+        {
+          defaultMessage: 'A maximum index size is required.',
+        }
+      ),
+      maximumDocumentsRequiredMessage: i18n.translate(
+        'xpack.indexLifecycleMgmt.editPolicy.errors.maximumDocumentsMissingError',
+        {
+          defaultMessage: 'Maximum documents is required.',
+        }
+      ),
+      rollOverConfigurationCallout: {
+        title: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.errors.rolloverConfigurationError.title',
+          {
+            defaultMessage: 'Invalid rollover configuration',
+          }
+        ),
+        body: i18n.translate(
+          'xpack.indexLifecycleMgmt.editPolicy.errors.rolloverConfigurationError.body',
+          {
+            defaultMessage:
+              'A value for one of maximum size, maximum documents, or maximum age is required.',
+          }
+        ),
+      },
+      nonNegativeNumberRequired: i18n.translate(
+        'xpack.indexLifecycleMgmt.editPolicy.errors.nonNegativeNumberRequiredError',
+        {
+          defaultMessage: 'Only non-negative numbers are allowed.',
+        }
+      ),
+    },
   },
 };
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts
index e0e1ad44f1557..90e81528f5afe 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts
@@ -4,40 +4,130 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-import { SerializedPolicy } from '../../../../common/types';
+import { isEmpty } from 'lodash';
 
-import { FormInternal } from './types';
+import { SerializedPolicy, SerializedActionWithAllocation } from '../../../../common/types';
+
+import { FormInternal, DataAllocationMetaFields } from './types';
+import { isNumber } from '../../services/policies/policy_serialization';
+
+const serializeAllocateAction = (
+  { dataTierAllocationType, allocationNodeAttribute }: DataAllocationMetaFields,
+  newActions: SerializedActionWithAllocation = {},
+  originalActions: SerializedActionWithAllocation = {}
+): SerializedActionWithAllocation => {
+  const { allocate, migrate, ...rest } = newActions;
+  // First copy over all non-allocate and migrate actions.
+  const actions: SerializedActionWithAllocation = { allocate, migrate, ...rest };
+
+  switch (dataTierAllocationType) {
+    case 'node_attrs':
+      if (allocationNodeAttribute) {
+        const [name, value] = allocationNodeAttribute.split(':');
+        actions.allocate = {
+          // copy over any other allocate details like "number_of_replicas"
+          ...actions.allocate,
+          require: {
+            [name]: value,
+          },
+        };
+      }
+
+      // copy over the original include and exclude values until we can set them in the form.
+      if (!isEmpty(originalActions?.allocate?.include)) {
+        actions.allocate = {
+          ...actions.allocate,
+          include: { ...originalActions?.allocate?.include },
+        };
+      }
+
+      if (!isEmpty(originalActions?.allocate?.exclude)) {
+        actions.allocate = {
+          ...actions.allocate,
+          exclude: { ...originalActions?.allocate?.exclude },
+        };
+      }
+      break;
+    case 'none':
+      actions.migrate = { enabled: false };
+      break;
+    default:
+  }
+  return actions;
+};
 
 export const createSerializer = (originalPolicy?: SerializedPolicy) => (
   data: FormInternal
 ): SerializedPolicy => {
-  const { _meta, ...rest } = data;
+  const { _meta, ...policy } = data;
 
-  if (!rest.phases || !rest.phases.hot) {
-    rest.phases = { hot: { actions: {} } };
+  if (!policy.phases || !policy.phases.hot) {
+    policy.phases = { hot: { actions: {} } };
   }
 
-  if (rest.phases.hot) {
-    rest.phases.hot.min_age = originalPolicy?.phases.hot?.min_age ?? '0ms';
+  /**
+   * HOT PHASE SERIALIZATION
+   */
+  if (policy.phases.hot) {
+    policy.phases.hot.min_age = originalPolicy?.phases.hot?.min_age ?? '0ms';
   }
 
-  if (rest.phases.hot?.actions) {
-    if (rest.phases.hot.actions?.rollover && _meta.hot.useRollover) {
-      if (rest.phases.hot.actions.rollover.max_age) {
-        rest.phases.hot.actions.rollover.max_age = `${rest.phases.hot.actions.rollover.max_age}${_meta.hot.maxAgeUnit}`;
+  if (policy.phases.hot?.actions) {
+    if (policy.phases.hot.actions?.rollover && _meta.hot.useRollover) {
+      if (policy.phases.hot.actions.rollover.max_age) {
+        policy.phases.hot.actions.rollover.max_age = `${policy.phases.hot.actions.rollover.max_age}${_meta.hot.maxAgeUnit}`;
       }
 
-      if (rest.phases.hot.actions.rollover.max_size) {
-        rest.phases.hot.actions.rollover.max_size = `${rest.phases.hot.actions.rollover.max_size}${_meta.hot.maxStorageSizeUnit}`;
+      if (policy.phases.hot.actions.rollover.max_size) {
+        policy.phases.hot.actions.rollover.max_size = `${policy.phases.hot.actions.rollover.max_size}${_meta.hot.maxStorageSizeUnit}`;
       }
 
-      if (_meta.hot.bestCompression && rest.phases.hot.actions?.forcemerge) {
-        rest.phases.hot.actions.forcemerge.index_codec = 'best_compression';
+      if (_meta.hot.bestCompression && policy.phases.hot.actions?.forcemerge) {
+        policy.phases.hot.actions.forcemerge.index_codec = 'best_compression';
       }
     } else {
-      delete rest.phases.hot.actions?.rollover;
+      delete policy.phases.hot.actions?.rollover;
+    }
+  }
+
+  /**
+   * WARM PHASE SERIALIZATION
+   */
+  if (policy.phases.warm) {
+    // If warm phase on rollover is enabled, delete min age field
+    // An index lifecycle switches to warm phase when rollover occurs, so you cannot specify a warm phase time
+    // They are mutually exclusive
+    if (_meta.hot.useRollover && _meta.warm.warmPhaseOnRollover) {
+      delete policy.phases.warm.min_age;
+    } else if (
+      (!_meta.hot.useRollover || !_meta.warm.warmPhaseOnRollover) &&
+      policy.phases.warm.min_age
+    ) {
+      policy.phases.warm.min_age = `${policy.phases.warm.min_age}${_meta.warm.minAgeUnit}`;
+    }
+
+    policy.phases.warm.actions = serializeAllocateAction(
+      _meta.warm,
+      policy.phases.warm.actions,
+      originalPolicy?.phases.warm?.actions
+    );
+
+    if (
+      policy.phases.warm.actions.allocate &&
+      !policy.phases.warm.actions.allocate.require &&
+      !isNumber(policy.phases.warm.actions.allocate.number_of_replicas) &&
+      isEmpty(policy.phases.warm.actions.allocate.include) &&
+      isEmpty(policy.phases.warm.actions.allocate.exclude)
+    ) {
+      // remove allocate action if it does not define require or number of nodes
+      // and both include and exclude are empty objects (ES will fail to parse if we don't)
+      delete policy.phases.warm.actions.allocate;
+    }
+
+    if (_meta.warm.bestCompression && policy.phases.warm.actions?.forcemerge) {
+      policy.phases.warm.actions.forcemerge.index_codec = 'best_compression';
     }
   }
 
-  return rest;
+  return policy;
 };
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts
index dba56eb8ecbf3..6fcfbd050c69d 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts
@@ -6,6 +6,29 @@
 
 import { SerializedPolicy } from '../../../../common/types';
 
+export type DataTierAllocationType = 'node_roles' | 'node_attrs' | 'none';
+
+export interface DataAllocationMetaFields {
+  dataTierAllocationType: DataTierAllocationType;
+  allocationNodeAttribute?: string;
+}
+
+interface HotPhaseMetaFields {
+  useRollover: boolean;
+  forceMergeEnabled: boolean;
+  bestCompression: boolean;
+  maxStorageSizeUnit?: string;
+  maxAgeUnit?: string;
+}
+
+interface WarmPhaseMetaFields extends DataAllocationMetaFields {
+  enabled: boolean;
+  forceMergeEnabled: boolean;
+  bestCompression: boolean;
+  warmPhaseOnRollover: boolean;
+  minAgeUnit?: string;
+}
+
 /**
  * Describes the shape of data after deserialization.
  */
@@ -15,12 +38,7 @@ export interface FormInternal extends SerializedPolicy {
    * certain form fields which affects what is ultimately serialized.
    */
   _meta: {
-    hot: {
-      useRollover: boolean;
-      forceMergeEnabled: boolean;
-      bestCompression: boolean;
-      maxStorageSizeUnit?: string;
-      maxAgeUnit?: string;
-    };
+    hot: HotPhaseMetaFields;
+    warm: WarmPhaseMetaFields;
   };
 }
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/cold_phase.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/cold_phase.ts
index 9f5f603fbc564..faf3954f93fd8 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/cold_phase.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/cold_phase.ts
@@ -13,7 +13,7 @@ import {
   PhaseValidationErrors,
   positiveNumberRequiredMessage,
 } from './policy_validation';
-import { determineDataTierAllocationType } from '../../lib';
+import { determineDataTierAllocationTypeLegacy } from '../../lib';
 import { serializePhaseWithAllocation } from './shared';
 
 export const coldPhaseInitialization: ColdPhase = {
@@ -35,10 +35,8 @@ export const coldPhaseFromES = (phaseSerialized?: SerializedColdPhase): ColdPhas
 
   phase.phaseEnabled = true;
 
-  if (phaseSerialized.actions.allocate) {
-    phase.dataTierAllocationType = determineDataTierAllocationType(
-      phaseSerialized.actions.allocate
-    );
+  if (phaseSerialized.actions) {
+    phase.dataTierAllocationType = determineDataTierAllocationTypeLegacy(phaseSerialized.actions);
   }
 
   if (phaseSerialized.min_age) {
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts
index 5c7f04986827b..0be6ab3521736 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts
@@ -7,7 +7,7 @@
 // eslint-disable-next-line no-restricted-imports
 import cloneDeep from 'lodash/cloneDeep';
 import { deserializePolicy, legacySerializePolicy } from './policy_serialization';
-import { defaultNewColdPhase, defaultNewDeletePhase, defaultNewWarmPhase } from '../../constants';
+import { defaultNewColdPhase, defaultNewDeletePhase } from '../../constants';
 import { DataTierAllocationType } from '../../../../common/types';
 import { coldPhaseInitialization } from './cold_phase';
 
@@ -18,13 +18,6 @@ describe('Policy serialization', () => {
         {
           name: 'test',
           phases: {
-            warm: {
-              ...defaultNewWarmPhase,
-              dataTierAllocationType: 'default',
-              // These selected attrs should be ignored
-              selectedNodeAttrs: 'another:thing',
-              phaseEnabled: true,
-            },
             cold: {
               ...defaultNewColdPhase,
               dataTierAllocationType: 'default',
@@ -38,9 +31,6 @@ describe('Policy serialization', () => {
           name: 'test',
           phases: {
             hot: { actions: {} },
-            warm: {
-              actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } },
-            },
             cold: {
               actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } },
             },
@@ -50,13 +40,6 @@ describe('Policy serialization', () => {
     ).toEqual({
       name: 'test',
       phases: {
-        warm: {
-          actions: {
-            set_priority: {
-              priority: 50,
-            },
-          },
-        },
         cold: {
           actions: {
             set_priority: {
@@ -75,12 +58,6 @@ describe('Policy serialization', () => {
         {
           name: 'test',
           phases: {
-            warm: {
-              ...defaultNewWarmPhase,
-              dataTierAllocationType: 'custom',
-              selectedNodeAttrs: 'another:thing',
-              phaseEnabled: true,
-            },
             cold: {
               ...defaultNewColdPhase,
               dataTierAllocationType: 'custom',
@@ -94,15 +71,6 @@ describe('Policy serialization', () => {
           name: 'test',
           phases: {
             hot: { actions: {} },
-            warm: {
-              actions: {
-                allocate: {
-                  include: { keep: 'this' },
-                  exclude: { keep: 'this' },
-                  require: { something: 'here' },
-                },
-              },
-            },
             cold: {
               actions: {
                 allocate: {
@@ -118,20 +86,6 @@ describe('Policy serialization', () => {
     ).toEqual({
       name: 'test',
       phases: {
-        warm: {
-          actions: {
-            allocate: {
-              include: { keep: 'this' },
-              exclude: { keep: 'this' },
-              require: {
-                another: 'thing',
-              },
-            },
-            set_priority: {
-              priority: 50,
-            },
-          },
-        },
         cold: {
           actions: {
             allocate: {
@@ -157,12 +111,6 @@ describe('Policy serialization', () => {
         {
           name: 'test',
           phases: {
-            warm: {
-              ...defaultNewWarmPhase,
-              dataTierAllocationType: 'custom',
-              selectedNodeAttrs: '',
-              phaseEnabled: true,
-            },
             cold: {
               ...defaultNewColdPhase,
               dataTierAllocationType: 'custom',
@@ -176,9 +124,6 @@ describe('Policy serialization', () => {
           name: 'test',
           phases: {
             hot: { actions: {} },
-            warm: {
-              actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } },
-            },
             cold: {
               actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } },
             },
@@ -189,14 +134,6 @@ describe('Policy serialization', () => {
       // There should be no allocation action in any phases...
       name: 'test',
       phases: {
-        warm: {
-          actions: {
-            allocate: { include: {}, exclude: {}, require: { something: 'here' } },
-            set_priority: {
-              priority: 50,
-            },
-          },
-        },
         cold: {
           actions: {
             allocate: { include: {}, exclude: {}, require: { something: 'here' } },
@@ -216,12 +153,6 @@ describe('Policy serialization', () => {
         {
           name: 'test',
           phases: {
-            warm: {
-              ...defaultNewWarmPhase,
-              dataTierAllocationType: 'none',
-              selectedNodeAttrs: 'ignore:this',
-              phaseEnabled: true,
-            },
             cold: {
               ...defaultNewColdPhase,
               dataTierAllocationType: 'none',
@@ -235,9 +166,6 @@ describe('Policy serialization', () => {
           name: 'test',
           phases: {
             hot: { actions: {} },
-            warm: {
-              actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } },
-            },
             cold: {
               actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } },
             },
@@ -248,16 +176,6 @@ describe('Policy serialization', () => {
       // There should be no allocation action in any phases...
       name: 'test',
       phases: {
-        warm: {
-          actions: {
-            migrate: {
-              enabled: false,
-            },
-            set_priority: {
-              priority: 50,
-            },
-          },
-        },
         cold: {
           actions: {
             migrate: {
@@ -277,9 +195,6 @@ describe('Policy serialization', () => {
     const originalPolicy = {
       name: 'test',
       phases: {
-        warm: {
-          actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } },
-        },
         cold: {
           actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } },
         },
@@ -291,12 +206,6 @@ describe('Policy serialization', () => {
     const deserializedPolicy = {
       name: 'test',
       phases: {
-        warm: {
-          ...defaultNewWarmPhase,
-          dataTierAllocationType: 'none' as DataTierAllocationType,
-          selectedNodeAttrs: 'ignore:this',
-          phaseEnabled: true,
-        },
         cold: {
           ...defaultNewColdPhase,
           dataTierAllocationType: 'none' as DataTierAllocationType,
@@ -308,10 +217,6 @@ describe('Policy serialization', () => {
       },
     };
 
-    legacySerializePolicy(deserializedPolicy, originalPolicy);
-    deserializedPolicy.phases.warm.dataTierAllocationType = 'custom';
-    legacySerializePolicy(deserializedPolicy, originalPolicy);
-    deserializedPolicy.phases.warm.dataTierAllocationType = 'default';
     legacySerializePolicy(deserializedPolicy, originalPolicy);
     expect(originalPolicy).toEqual(originalClone);
   });
@@ -322,13 +227,6 @@ describe('Policy serialization', () => {
         {
           name: 'test',
           phases: {
-            warm: {
-              ...defaultNewWarmPhase,
-              phaseEnabled: true,
-              forceMergeEnabled: true,
-              selectedForceMergeSegments: '1',
-              bestCompressionEnabled: true,
-            },
             cold: {
               ...defaultNewColdPhase,
             },
@@ -344,19 +242,7 @@ describe('Policy serialization', () => {
       )
     ).toEqual({
       name: 'test',
-      phases: {
-        warm: {
-          actions: {
-            forcemerge: {
-              max_num_segments: 1,
-              index_codec: 'best_compression',
-            },
-            set_priority: {
-              priority: 50,
-            },
-          },
-        },
-      },
+      phases: {},
     });
   });
 
@@ -384,31 +270,12 @@ describe('Policy serialization', () => {
                 },
               },
             },
-            warm: {
-              actions: {
-                forcemerge: {
-                  max_num_segments: 1,
-                  index_codec: 'best_compression',
-                },
-                set_priority: {
-                  priority: 50,
-                },
-              },
-            },
           },
         },
       })
     ).toEqual({
       name: 'test',
       phases: {
-        warm: {
-          ...defaultNewWarmPhase,
-          warmPhaseOnRollover: false,
-          phaseEnabled: true,
-          forceMergeEnabled: true,
-          selectedForceMergeSegments: '1',
-          bestCompressionEnabled: true,
-        },
         cold: {
           ...coldPhaseInitialization,
         },
@@ -423,13 +290,6 @@ describe('Policy serialization', () => {
         {
           name: 'test',
           phases: {
-            warm: {
-              ...defaultNewWarmPhase,
-              phaseEnabled: true,
-              forceMergeEnabled: true,
-              selectedForceMergeSegments: '1',
-              bestCompressionEnabled: false,
-            },
             cold: {
               ...defaultNewColdPhase,
             },
@@ -438,32 +298,12 @@ describe('Policy serialization', () => {
         },
         {
           name: 'test',
-          phases: {
-            warm: {
-              actions: {
-                forcemerge: {
-                  max_num_segments: 1,
-                  index_codec: 'best_compression',
-                },
-              },
-            },
-          },
+          phases: {},
         }
       )
     ).toEqual({
       name: 'test',
-      phases: {
-        warm: {
-          actions: {
-            forcemerge: {
-              max_num_segments: 1,
-            },
-            set_priority: {
-              priority: 50,
-            },
-          },
-        },
-      },
+      phases: {},
     });
   });
 });
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts
index 0dce7efce4623..32c7e698b0920 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts
@@ -9,11 +9,9 @@ import { LegacyPolicy, PolicyFromES, SerializedPolicy } from '../../../../common
 import {
   defaultNewColdPhase,
   defaultNewDeletePhase,
-  defaultNewWarmPhase,
   serializedPhaseInitialization,
 } from '../../constants';
 
-import { warmPhaseFromES, warmPhaseToES } from './warm_phase';
 import { coldPhaseFromES, coldPhaseToES } from './cold_phase';
 import { deletePhaseFromES, deletePhaseToES } from './delete_phase';
 
@@ -48,7 +46,6 @@ export const initializeNewPolicy = (newPolicyName: string = ''): LegacyPolicy =>
   return {
     name: newPolicyName,
     phases: {
-      warm: { ...defaultNewWarmPhase },
       cold: { ...defaultNewColdPhase },
       delete: { ...defaultNewDeletePhase },
     },
@@ -64,7 +61,6 @@ export const deserializePolicy = (policy: PolicyFromES): LegacyPolicy => {
   return {
     name,
     phases: {
-      warm: warmPhaseFromES(phases.warm),
       cold: coldPhaseFromES(phases.cold),
       delete: deletePhaseFromES(phases.delete),
     },
@@ -82,9 +78,6 @@ export const legacySerializePolicy = (
     name: policy.name,
     phases: {},
   } as SerializedPolicy;
-  if (policy.phases.warm.phaseEnabled) {
-    serializedPolicy.phases.warm = warmPhaseToES(policy.phases.warm, originalEsPolicy.phases.warm);
-  }
 
   if (policy.phases.cold.phaseEnabled) {
     serializedPolicy.phases.cold = coldPhaseToES(policy.phases.cold, originalEsPolicy.phases.cold);
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts
index eeceb97c409f5..a113cb68a2349 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts
@@ -5,14 +5,7 @@
  */
 
 import { i18n } from '@kbn/i18n';
-import {
-  ColdPhase,
-  DeletePhase,
-  LegacyPolicy,
-  PolicyFromES,
-  WarmPhase,
-} from '../../../../common/types';
-import { validateWarmPhase } from './warm_phase';
+import { ColdPhase, DeletePhase, LegacyPolicy, PolicyFromES } from '../../../../common/types';
 import { validateColdPhase } from './cold_phase';
 import { validateDeletePhase } from './delete_phase';
 
@@ -89,7 +82,6 @@ export type PhaseValidationErrors<T> = {
 };
 
 export interface ValidationErrors {
-  warm: PhaseValidationErrors<WarmPhase>;
   cold: PhaseValidationErrors<ColdPhase>;
   delete: PhaseValidationErrors<DeletePhase>;
   policyName: string[];
@@ -128,19 +120,16 @@ export const validatePolicy = (
     }
   }
 
-  const warmPhaseErrors = validateWarmPhase(policy.phases.warm);
   const coldPhaseErrors = validateColdPhase(policy.phases.cold);
   const deletePhaseErrors = validateDeletePhase(policy.phases.delete);
   const isValid =
     policyNameErrors.length === 0 &&
-    Object.keys(warmPhaseErrors).length === 0 &&
     Object.keys(coldPhaseErrors).length === 0 &&
     Object.keys(deletePhaseErrors).length === 0;
   return [
     isValid,
     {
       policyName: [...policyNameErrors],
-      warm: warmPhaseErrors,
       cold: coldPhaseErrors,
       delete: deletePhaseErrors,
     },
@@ -156,9 +145,6 @@ export const findFirstError = (errors?: ValidationErrors): string | undefined =>
     return propertyof<ValidationErrors>('policyName');
   }
 
-  if (Object.keys(errors.warm).length > 0) {
-    return `${propertyof<ValidationErrors>('warm')}.${Object.keys(errors.warm)[0]}`;
-  }
   if (Object.keys(errors.cold).length > 0) {
     return `${propertyof<ValidationErrors>('cold')}.${Object.keys(errors.cold)[0]}`;
   }
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/warm_phase.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/warm_phase.ts
deleted file mode 100644
index 436e5a222f86d..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/warm_phase.ts
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { isEmpty } from 'lodash';
-import { AllocateAction, WarmPhase, SerializedWarmPhase } from '../../../../common/types';
-import { serializedPhaseInitialization } from '../../constants';
-import { isNumber, splitSizeAndUnits } from './policy_serialization';
-
-import {
-  numberRequiredMessage,
-  PhaseValidationErrors,
-  positiveNumberRequiredMessage,
-  positiveNumbersAboveZeroErrorMessage,
-} from './policy_validation';
-
-import { determineDataTierAllocationType } from '../../lib';
-import { serializePhaseWithAllocation } from './shared';
-
-const warmPhaseInitialization: WarmPhase = {
-  phaseEnabled: false,
-  warmPhaseOnRollover: false,
-  selectedMinimumAge: '0',
-  selectedMinimumAgeUnits: 'd',
-  selectedNodeAttrs: '',
-  selectedReplicaCount: '',
-  shrinkEnabled: false,
-  selectedPrimaryShardCount: '',
-  forceMergeEnabled: false,
-  selectedForceMergeSegments: '',
-  bestCompressionEnabled: false,
-  phaseIndexPriority: '',
-  dataTierAllocationType: 'default',
-};
-
-export const warmPhaseFromES = (phaseSerialized?: SerializedWarmPhase): WarmPhase => {
-  const phase: WarmPhase = { ...warmPhaseInitialization };
-
-  if (phaseSerialized === undefined || phaseSerialized === null) {
-    return phase;
-  }
-
-  phase.phaseEnabled = true;
-
-  if (phaseSerialized.actions.allocate) {
-    phase.dataTierAllocationType = determineDataTierAllocationType(
-      phaseSerialized.actions.allocate
-    );
-  }
-
-  if (phaseSerialized.min_age) {
-    if (phaseSerialized.min_age === '0ms') {
-      phase.warmPhaseOnRollover = true;
-    } else {
-      const { size: minAge, units: minAgeUnits } = splitSizeAndUnits(phaseSerialized.min_age);
-      phase.selectedMinimumAge = minAge;
-      phase.selectedMinimumAgeUnits = minAgeUnits;
-    }
-  }
-  if (phaseSerialized.actions) {
-    const actions = phaseSerialized.actions;
-    if (actions.allocate) {
-      const allocate = actions.allocate;
-      if (allocate.require) {
-        Object.entries(allocate.require).forEach((entry) => {
-          phase.selectedNodeAttrs = entry.join(':');
-        });
-        if (allocate.number_of_replicas) {
-          phase.selectedReplicaCount = allocate.number_of_replicas.toString();
-        }
-      }
-    }
-
-    if (actions.forcemerge) {
-      const forcemerge = actions.forcemerge;
-      phase.forceMergeEnabled = true;
-      phase.selectedForceMergeSegments = forcemerge.max_num_segments.toString();
-      // only accepted value for index_codec
-      phase.bestCompressionEnabled = forcemerge.index_codec === 'best_compression';
-    }
-
-    if (actions.shrink) {
-      phase.shrinkEnabled = true;
-      phase.selectedPrimaryShardCount = actions.shrink.number_of_shards
-        ? actions.shrink.number_of_shards.toString()
-        : '';
-    }
-
-    if (actions.set_priority) {
-      phase.phaseIndexPriority = actions.set_priority.priority
-        ? actions.set_priority.priority.toString()
-        : '';
-    }
-  }
-  return phase;
-};
-
-export const warmPhaseToES = (
-  phase: WarmPhase,
-  originalEsPhase?: SerializedWarmPhase
-): SerializedWarmPhase => {
-  if (!originalEsPhase) {
-    originalEsPhase = { ...serializedPhaseInitialization };
-  }
-
-  const esPhase = { ...originalEsPhase };
-
-  if (isNumber(phase.selectedMinimumAge)) {
-    esPhase.min_age = `${phase.selectedMinimumAge}${phase.selectedMinimumAgeUnits}`;
-  }
-
-  // If warm phase on rollover is enabled, delete min age field
-  // An index lifecycle switches to warm phase when rollover occurs, so you cannot specify a warm phase time
-  // They are mutually exclusive
-  if (phase.warmPhaseOnRollover) {
-    delete esPhase.min_age;
-  }
-
-  esPhase.actions = serializePhaseWithAllocation(phase, esPhase.actions);
-
-  if (isNumber(phase.selectedReplicaCount)) {
-    esPhase.actions.allocate = esPhase.actions.allocate || ({} as AllocateAction);
-    esPhase.actions.allocate.number_of_replicas = parseInt(phase.selectedReplicaCount, 10);
-  } else {
-    if (esPhase.actions.allocate) {
-      delete esPhase.actions.allocate.number_of_replicas;
-    }
-  }
-
-  if (
-    esPhase.actions.allocate &&
-    !esPhase.actions.allocate.require &&
-    !isNumber(esPhase.actions.allocate.number_of_replicas) &&
-    isEmpty(esPhase.actions.allocate.include) &&
-    isEmpty(esPhase.actions.allocate.exclude)
-  ) {
-    // remove allocate action if it does not define require or number of nodes
-    // and both include and exclude are empty objects (ES will fail to parse if we don't)
-    delete esPhase.actions.allocate;
-  }
-
-  if (phase.forceMergeEnabled) {
-    esPhase.actions.forcemerge = {
-      max_num_segments: parseInt(phase.selectedForceMergeSegments, 10),
-    };
-    if (phase.bestCompressionEnabled) {
-      // only accepted value for index_codec
-      esPhase.actions.forcemerge.index_codec = 'best_compression';
-    }
-  } else {
-    delete esPhase.actions.forcemerge;
-  }
-
-  if (phase.shrinkEnabled && isNumber(phase.selectedPrimaryShardCount)) {
-    esPhase.actions.shrink = {
-      number_of_shards: parseInt(phase.selectedPrimaryShardCount, 10),
-    };
-  } else {
-    delete esPhase.actions.shrink;
-  }
-
-  if (isNumber(phase.phaseIndexPriority)) {
-    esPhase.actions.set_priority = {
-      priority: parseInt(phase.phaseIndexPriority, 10),
-    };
-  } else {
-    delete esPhase.actions.set_priority;
-  }
-
-  return esPhase;
-};
-
-export const validateWarmPhase = (phase: WarmPhase): PhaseValidationErrors<WarmPhase> => {
-  if (!phase.phaseEnabled) {
-    return {};
-  }
-
-  const phaseErrors = {} as PhaseValidationErrors<WarmPhase>;
-
-  // index priority is optional, but if it's set, it needs to be a positive number
-  if (phase.phaseIndexPriority) {
-    if (!isNumber(phase.phaseIndexPriority)) {
-      phaseErrors.phaseIndexPriority = [numberRequiredMessage];
-    } else if (parseInt(phase.phaseIndexPriority, 10) < 0) {
-      phaseErrors.phaseIndexPriority = [positiveNumberRequiredMessage];
-    }
-  }
-
-  // if warm phase on rollover is disabled, min age needs to be a positive number
-  if (!phase.warmPhaseOnRollover) {
-    if (!isNumber(phase.selectedMinimumAge)) {
-      phaseErrors.selectedMinimumAge = [numberRequiredMessage];
-    } else if (parseInt(phase.selectedMinimumAge, 10) < 0) {
-      phaseErrors.selectedMinimumAge = [positiveNumberRequiredMessage];
-    }
-  }
-
-  // if forcemerge is enabled, force merge segments needs to be a number above zero
-  if (phase.forceMergeEnabled) {
-    if (!isNumber(phase.selectedForceMergeSegments)) {
-      phaseErrors.selectedForceMergeSegments = [numberRequiredMessage];
-    } else if (parseInt(phase.selectedForceMergeSegments, 10) < 1) {
-      phaseErrors.selectedForceMergeSegments = [positiveNumbersAboveZeroErrorMessage];
-    }
-  }
-
-  // if shrink is enabled, primary shard count needs to be a number above zero
-  if (phase.shrinkEnabled) {
-    if (!isNumber(phase.selectedPrimaryShardCount)) {
-      phaseErrors.selectedPrimaryShardCount = [numberRequiredMessage];
-    } else if (parseInt(phase.selectedPrimaryShardCount, 10) < 1) {
-      phaseErrors.selectedPrimaryShardCount = [positiveNumbersAboveZeroErrorMessage];
-    }
-  }
-
-  // replica count is optional, but if it's set, it needs to be a positive number
-  if (phase.selectedReplicaCount) {
-    if (!isNumber(phase.selectedReplicaCount)) {
-      phaseErrors.selectedReplicaCount = [numberRequiredMessage];
-    } else if (parseInt(phase.selectedReplicaCount, 10) < 0) {
-      phaseErrors.selectedReplicaCount = [numberRequiredMessage];
-    }
-  }
-
-  return {
-    ...phaseErrors,
-  };
-};
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts
index 81eb1c8cad135..c77e3d22f0e37 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts
@@ -9,8 +9,8 @@ import {
   UIM_CONFIG_WARM_PHASE,
   UIM_CONFIG_SET_PRIORITY,
   UIM_CONFIG_FREEZE_INDEX,
-  defaultNewWarmPhase,
   defaultNewColdPhase,
+  defaultPhaseIndexPriority,
 } from '../constants/';
 
 import { getUiMetricsForPhases } from './ui_metric';
@@ -38,7 +38,7 @@ describe('getUiMetricsForPhases', () => {
           min_age: '0ms',
           actions: {
             set_priority: {
-              priority: parseInt(defaultNewWarmPhase.phaseIndexPriority, 10),
+              priority: parseInt(defaultPhaseIndexPriority, 10),
             },
           },
         },
@@ -53,7 +53,7 @@ describe('getUiMetricsForPhases', () => {
           min_age: '0ms',
           actions: {
             set_priority: {
-              priority: parseInt(defaultNewWarmPhase.phaseIndexPriority, 10) + 1,
+              priority: parseInt(defaultPhaseIndexPriority, 10) + 1,
             },
           },
         },
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts
index ea5c5619da589..305b35b23e4d8 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts
@@ -14,8 +14,8 @@ import {
   UIM_CONFIG_SET_PRIORITY,
   UIM_CONFIG_WARM_PHASE,
   defaultNewColdPhase,
-  defaultNewWarmPhase,
   defaultSetPriority,
+  defaultPhaseIndexPriority,
 } from '../constants';
 
 import { Phases } from '../../../common/types';
@@ -50,8 +50,7 @@ export function getUiMetricsForPhases(phases: Phases): string[] {
         const isWarmPhasePriorityChanged =
           phases.warm &&
           phases.warm.actions.set_priority &&
-          phases.warm.actions.set_priority.priority !==
-            parseInt(defaultNewWarmPhase.phaseIndexPriority, 10);
+          phases.warm.actions.set_priority.priority !== parseInt(defaultPhaseIndexPriority, 10);
 
         const isColdPhasePriorityChanged =
           phases.cold &&
diff --git a/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts b/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts
index dc3e1b1d1b62d..023aeba57aa7a 100644
--- a/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts
@@ -26,6 +26,7 @@ export {
   ToggleField,
   NumericField,
   SelectField,
+  SuperSelectField,
 } from '../../../../src/plugins/es_ui_shared/static/forms/components';
 
 export { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public';
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts
index 53955d93c1e09..0603ebf6eebe0 100644
--- a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts
@@ -4,7 +4,7 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-import { ListNodesRouteResponse, NodeDataRole } from '../../../../common/types';
+import { ListNodesRouteResponse, DataTierRole } from '../../../../common/types';
 
 import { RouteDependencies } from '../../../types';
 import { addBasePath } from '../../../services';
@@ -39,10 +39,10 @@ export function convertSettingsIntoLists(
         }
       }
 
-      const dataRoles = nodeSettings.roles.filter((r) => r.startsWith('data')) as NodeDataRole[];
+      const dataRoles = nodeSettings.roles.filter((r) => r.startsWith('data')) as DataTierRole[];
       for (const role of dataRoles) {
-        accum.nodesByRoles[role as NodeDataRole] = accum.nodesByRoles[role] ?? [];
-        accum.nodesByRoles[role as NodeDataRole]!.push(nodeId);
+        accum.nodesByRoles[role as DataTierRole] = accum.nodesByRoles[role] ?? [];
+        accum.nodesByRoles[role as DataTierRole]!.push(nodeId);
       }
 
       // If we detect a single node using legacy "data:true" setting we know we are not using data roles for
diff --git a/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts
index 2dcab5b49dcdb..2d84e36f3a3ac 100644
--- a/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts
+++ b/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts
@@ -26,7 +26,6 @@ import {
   RequestHandlerContext,
   KibanaResponseFactory,
   RouteMethod,
-  LegacyAPICaller,
 } from '../../../../../../../src/core/server';
 import { RequestHandler } from '../../../../../../../src/core/server';
 import { InfraConfig } from '../../../plugin';
@@ -218,11 +217,7 @@ export class KibanaFramework {
   }
 
   public getIndexPatternsService(requestContext: RequestHandlerContext): IndexPatternsFetcher {
-    return new IndexPatternsFetcher((...rest: Parameters<LegacyAPICaller>) => {
-      rest[1] = rest[1] || {};
-      rest[1].allowNoIndices = true;
-      return requestContext.core.elasticsearch.legacy.client.callAsCurrentUser(...rest);
-    });
+    return new IndexPatternsFetcher(requestContext.core.elasticsearch.client.asCurrentUser, true);
   }
 
   public getSpaceId(request: KibanaRequest): string {
diff --git a/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.ts b/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.ts
index 93948a8b8797e..c4f2c5f7981d4 100644
--- a/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.ts
+++ b/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.ts
@@ -9,7 +9,7 @@ import { MetricsAPIMetric, MetricsExplorerMetric } from '../../../../common/http
 export const convertMetricToMetricsAPIMetric = (
   metric: MetricsExplorerMetric,
   index: number
-): MetricsAPIMetric => {
+): MetricsAPIMetric | undefined => {
   const id = `metric_${index}`;
   if (metric.aggregation === 'rate' && metric.field) {
     return {
@@ -44,19 +44,21 @@ export const convertMetricToMetricsAPIMetric = (
     };
   }
 
-  return {
-    id,
-    aggregations: {
-      [id]: {
-        bucket_script: {
-          buckets_path: { count: '_count' },
-          script: {
-            source: 'count * 1',
-            lang: 'expression',
+  if (metric.aggregation === 'count') {
+    return {
+      id,
+      aggregations: {
+        [id]: {
+          bucket_script: {
+            buckets_path: { count: '_count' },
+            script: {
+              source: 'count * 1',
+              lang: 'expression',
+            },
+            gap_policy: 'skip',
           },
-          gap_policy: 'skip',
         },
       },
-    },
-  };
+    };
+  }
 };
diff --git a/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_request_to_metrics_api_options.test.ts b/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_request_to_metrics_api_options.test.ts
index 4c423aee347e9..887f464b1a564 100644
--- a/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_request_to_metrics_api_options.test.ts
+++ b/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_request_to_metrics_api_options.test.ts
@@ -120,4 +120,16 @@ describe('convertRequestToMetricsAPIOptions', () => {
       metrics: [],
     });
   });
+
+  it('should work with empty field', () => {
+    expect(
+      convertRequestToMetricsAPIOptions({
+        ...BASE_REQUEST,
+        metrics: [{ aggregation: 'avg' }],
+      })
+    ).toEqual({
+      ...BASE_METRICS_UI_OPTIONS,
+      metrics: [],
+    });
+  });
 });
diff --git a/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_request_to_metrics_api_options.ts b/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_request_to_metrics_api_options.ts
index 2dd00c4aed59c..4bb6d8f55a11a 100644
--- a/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_request_to_metrics_api_options.ts
+++ b/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_request_to_metrics_api_options.ts
@@ -15,7 +15,9 @@ import { convertMetricToMetricsAPIMetric } from './convert_metric_to_metrics_api
 export const convertRequestToMetricsAPIOptions = (
   options: MetricsExplorerRequestBody
 ): MetricsAPIRequest => {
-  const metrics = options.metrics.map(convertMetricToMetricsAPIMetric);
+  const metrics = options.metrics
+    .map(convertMetricToMetricsAPIMetric)
+    .filter(<M>(m: M): m is NonNullable<M> => !!m);
   const { limit, timerange, indexPattern } = options;
 
   const metricsApiOptions: MetricsAPIRequest = {
diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx
index d71b90d16725d..5d39995922b93 100644
--- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx
+++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx
@@ -18,7 +18,9 @@ interface Props {
 }
 
 const Container = styled.div`
-  min-height: calc(100vh - ${(props) => props.theme.eui.euiHeaderChildSize});
+  min-height: calc(
+    100vh - ${(props) => parseFloat(props.theme.eui.euiHeaderHeightCompensation) * 2}px
+  );
   background: ${(props) => props.theme.eui.euiColorEmptyShade};
   display: flex;
   flex-direction: column;
diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx
index fa9ce24935429..af4c2f78f14a2 100644
--- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx
+++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx
@@ -22,7 +22,6 @@ import { useCapabilities, useLink } from '../../../../../hooks';
 import { useAgentPolicyRefresh } from '../../hooks';
 
 interface InMemoryPackagePolicy extends PackagePolicy {
-  inputTypes: string[];
   packageName?: string;
   packageTitle?: string;
   packageVersion?: string;
@@ -56,11 +55,7 @@ export const PackagePoliciesTable: React.FunctionComponent<Props> = ({
   // With the package policies provided on input, generate the list of package policies
   // used in the InMemoryTable (flattens some values for search) as well as
   // the list of options that will be used in the filters dropdowns
-  const [packagePolicies, namespaces, inputTypes] = useMemo((): [
-    InMemoryPackagePolicy[],
-    FilterOption[],
-    FilterOption[]
-  ] => {
+  const [packagePolicies, namespaces] = useMemo((): [InMemoryPackagePolicy[], FilterOption[]] => {
     const namespacesValues: string[] = [];
     const inputTypesValues: string[] = [];
     const mappedPackagePolicies = originalPackagePolicies.map<InMemoryPackagePolicy>(
@@ -69,13 +64,8 @@ export const PackagePoliciesTable: React.FunctionComponent<Props> = ({
           namespacesValues.push(packagePolicy.namespace);
         }
 
-        const dsInputTypes: string[] = [];
-
-        dsInputTypes.sort(stringSortAscending);
-
         return {
           ...packagePolicy,
-          inputTypes: dsInputTypes,
           packageName: packagePolicy.package?.name ?? '',
           packageTitle: packagePolicy.package?.title ?? '',
           packageVersion: packagePolicy.package?.version ?? '',
@@ -86,11 +76,7 @@ export const PackagePoliciesTable: React.FunctionComponent<Props> = ({
     namespacesValues.sort(stringSortAscending);
     inputTypesValues.sort(stringSortAscending);
 
-    return [
-      mappedPackagePolicies,
-      namespacesValues.map(toFilterOption),
-      inputTypesValues.map(toFilterOption),
-    ];
+    return [mappedPackagePolicies, namespacesValues.map(toFilterOption)];
   }, [originalPackagePolicies]);
 
   const columns = useMemo(
@@ -273,13 +259,7 @@ export const PackagePoliciesTable: React.FunctionComponent<Props> = ({
             name: 'Namespace',
             options: namespaces,
             multiSelect: 'or',
-          },
-          {
-            type: 'field_value_selection',
-            field: 'inputTypes',
-            name: 'Input types',
-            options: inputTypes,
-            multiSelect: 'or',
+            operator: 'exact',
           },
         ],
       }}
diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/index.tsx
index bb109d766c50a..4e32fa0bbc1b9 100644
--- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/index.tsx
+++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/index.tsx
@@ -182,7 +182,12 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => {
     []
   );
 
-  const filterOptions: { [key: string]: string[] } = {
+  const filterOptions: {
+    [key: string]: Array<{
+      value: string;
+      name: string;
+    }>;
+  } = {
     dataset: [],
     type: [],
     namespace: [],
@@ -190,21 +195,37 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => {
   };
 
   if (dataStreamsData && dataStreamsData.data_streams.length) {
+    const dataValues: {
+      [key: string]: string[];
+    } = {
+      dataset: [],
+      type: [],
+      namespace: [],
+      package: [],
+    };
     dataStreamsData.data_streams.forEach((stream) => {
       const { dataset, type, namespace, package: pkg } = stream;
-      if (!filterOptions.dataset.includes(dataset)) {
-        filterOptions.dataset.push(dataset);
+      if (!dataValues.dataset.includes(dataset)) {
+        dataValues.dataset.push(dataset);
       }
-      if (!filterOptions.type.includes(type)) {
-        filterOptions.type.push(type);
+      if (!dataValues.type.includes(type)) {
+        dataValues.type.push(type);
       }
-      if (!filterOptions.namespace.includes(namespace)) {
-        filterOptions.namespace.push(namespace);
+      if (!dataValues.namespace.includes(namespace)) {
+        dataValues.namespace.push(namespace);
       }
-      if (!filterOptions.package.includes(pkg)) {
-        filterOptions.package.push(pkg);
+      if (!dataValues.package.includes(pkg)) {
+        dataValues.package.push(pkg);
       }
     });
+    for (const field in dataValues) {
+      if (filterOptions[field]) {
+        filterOptions[field] = dataValues[field].sort().map((option) => ({
+          value: option,
+          name: option,
+        }));
+      }
+    }
   }
 
   return (
@@ -266,10 +287,8 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => {
                 defaultMessage: 'Dataset',
               }),
               multiSelect: 'or',
-              options: filterOptions.dataset.map((option) => ({
-                value: option,
-                name: option,
-              })),
+              operator: 'exact',
+              options: filterOptions.dataset,
             },
             {
               type: 'field_value_selection',
@@ -278,10 +297,8 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => {
                 defaultMessage: 'Type',
               }),
               multiSelect: 'or',
-              options: filterOptions.type.map((option) => ({
-                value: option,
-                name: option,
-              })),
+              operator: 'exact',
+              options: filterOptions.type,
             },
             {
               type: 'field_value_selection',
@@ -290,10 +307,8 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => {
                 defaultMessage: 'Namespace',
               }),
               multiSelect: 'or',
-              options: filterOptions.namespace.map((option) => ({
-                value: option,
-                name: option,
-              })),
+              operator: 'exact',
+              options: filterOptions.namespace,
             },
             {
               type: 'field_value_selection',
@@ -302,10 +317,8 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => {
                 defaultMessage: 'Integration',
               }),
               multiSelect: 'or',
-              options: filterOptions.package.map((option) => ({
-                value: option,
-                name: option,
-              })),
+              operator: 'exact',
+              options: filterOptions.package,
             },
           ],
         }}
diff --git a/x-pack/plugins/ingest_manager/server/services/agent_policy.ts b/x-pack/plugins/ingest_manager/server/services/agent_policy.ts
index 19d69a33788c6..b003d16d379ca 100644
--- a/x-pack/plugins/ingest_manager/server/services/agent_policy.ts
+++ b/x-pack/plugins/ingest_manager/server/services/agent_policy.ts
@@ -83,7 +83,12 @@ class AgentPolicyService {
     return (await this.get(soClient, id)) as AgentPolicy;
   }
 
-  public async ensureDefaultAgentPolicy(soClient: SavedObjectsClientContract) {
+  public async ensureDefaultAgentPolicy(
+    soClient: SavedObjectsClientContract
+  ): Promise<{
+    created: boolean;
+    defaultAgentPolicy: AgentPolicy;
+  }> {
     const agentPolicies = await soClient.find<AgentPolicySOAttributes>({
       type: AGENT_POLICY_SAVED_OBJECT_TYPE,
       searchFields: ['is_default'],
@@ -95,12 +100,18 @@ class AgentPolicyService {
         ...DEFAULT_AGENT_POLICY,
       };
 
-      return this.create(soClient, newDefaultAgentPolicy);
+      return {
+        created: true,
+        defaultAgentPolicy: await this.create(soClient, newDefaultAgentPolicy),
+      };
     }
 
     return {
-      id: agentPolicies.saved_objects[0].id,
-      ...agentPolicies.saved_objects[0].attributes,
+      created: false,
+      defaultAgentPolicy: {
+        id: agentPolicies.saved_objects[0].id,
+        ...agentPolicies.saved_objects[0].attributes,
+      },
     };
   }
 
@@ -404,7 +415,9 @@ class AgentPolicyService {
       throw new Error('Agent policy not found');
     }
 
-    const { id: defaultAgentPolicyId } = await this.ensureDefaultAgentPolicy(soClient);
+    const {
+      defaultAgentPolicy: { id: defaultAgentPolicyId },
+    } = await this.ensureDefaultAgentPolicy(soClient);
     if (id === defaultAgentPolicyId) {
       throw new Error('The default agent policy cannot be deleted');
     }
diff --git a/x-pack/plugins/ingest_manager/server/services/setup.ts b/x-pack/plugins/ingest_manager/server/services/setup.ts
index 7f379d3ea4f13..741a23824f010 100644
--- a/x-pack/plugins/ingest_manager/server/services/setup.ts
+++ b/x-pack/plugins/ingest_manager/server/services/setup.ts
@@ -49,7 +49,11 @@ async function createSetupSideEffects(
   soClient: SavedObjectsClientContract,
   callCluster: CallESAsCurrentUser
 ): Promise<SetupStatus> {
-  const [installedPackages, defaultOutput, defaultAgentPolicy] = await Promise.all([
+  const [
+    installedPackages,
+    defaultOutput,
+    { created: defaultAgentPolicyCreated, defaultAgentPolicy },
+  ] = await Promise.all([
     // packages installed by default
     ensureInstalledDefaultPackages(soClient, callCluster),
     outputService.ensureDefaultOutput(soClient),
@@ -66,44 +70,46 @@ async function createSetupSideEffects(
     }),
   ]);
 
-  // ensure default packages are added to the default conifg
-  const agentPolicyWithPackagePolicies = await agentPolicyService.get(
-    soClient,
-    defaultAgentPolicy.id,
-    true
-  );
-  if (!agentPolicyWithPackagePolicies) {
-    throw new Error('Policy not found');
-  }
-  if (
-    agentPolicyWithPackagePolicies.package_policies.length &&
-    typeof agentPolicyWithPackagePolicies.package_policies[0] === 'string'
-  ) {
-    throw new Error('Policy not found');
-  }
-
-  for (const installedPackage of installedPackages) {
-    const packageShouldBeInstalled = DEFAULT_AGENT_POLICIES_PACKAGES.some(
-      (packageName) => installedPackage.name === packageName
+  // If we just created the default policy, ensure default packages are added to it
+  if (defaultAgentPolicyCreated) {
+    const agentPolicyWithPackagePolicies = await agentPolicyService.get(
+      soClient,
+      defaultAgentPolicy.id,
+      true
     );
-    if (!packageShouldBeInstalled) {
-      continue;
+    if (!agentPolicyWithPackagePolicies) {
+      throw new Error('Policy not found');
+    }
+    if (
+      agentPolicyWithPackagePolicies.package_policies.length &&
+      typeof agentPolicyWithPackagePolicies.package_policies[0] === 'string'
+    ) {
+      throw new Error('Policy not found');
     }
 
-    const isInstalled = agentPolicyWithPackagePolicies.package_policies.some(
-      (d: PackagePolicy | string) => {
-        return typeof d !== 'string' && d.package?.name === installedPackage.name;
+    for (const installedPackage of installedPackages) {
+      const packageShouldBeInstalled = DEFAULT_AGENT_POLICIES_PACKAGES.some(
+        (packageName) => installedPackage.name === packageName
+      );
+      if (!packageShouldBeInstalled) {
+        continue;
       }
-    );
 
-    if (!isInstalled) {
-      await addPackageToAgentPolicy(
-        soClient,
-        callCluster,
-        installedPackage,
-        agentPolicyWithPackagePolicies,
-        defaultOutput
+      const isInstalled = agentPolicyWithPackagePolicies.package_policies.some(
+        (d: PackagePolicy | string) => {
+          return typeof d !== 'string' && d.package?.name === installedPackage.name;
+        }
       );
+
+      if (!isInstalled) {
+        await addPackageToAgentPolicy(
+          soClient,
+          callCluster,
+          installedPackage,
+          agentPolicyWithPackagePolicies,
+          defaultOutput
+        );
+      }
     }
   }
 
diff --git a/x-pack/plugins/lens/public/app_plugin/mounter.tsx b/x-pack/plugins/lens/public/app_plugin/mounter.tsx
index 3943cbc54f0b3..ac5d145eedd5b 100644
--- a/x-pack/plugins/lens/public/app_plugin/mounter.tsx
+++ b/x-pack/plugins/lens/public/app_plugin/mounter.tsx
@@ -97,9 +97,12 @@ export async function mountApp(
 
   const redirectTo = (routeProps: RouteComponentProps<{ id?: string }>, savedObjectId?: string) => {
     if (!savedObjectId) {
-      routeProps.history.push('/');
+      routeProps.history.push({ pathname: '/', search: routeProps.history.location.search });
     } else {
-      routeProps.history.push(`/edit/${savedObjectId}`);
+      routeProps.history.push({
+        pathname: `/edit/${savedObjectId}`,
+        search: routeProps.history.location.search,
+      });
     }
   };
 
diff --git a/x-pack/plugins/lens/server/plugin.tsx b/x-pack/plugins/lens/server/plugin.tsx
index b801d30f5ba9b..a8f9bef92349c 100644
--- a/x-pack/plugins/lens/server/plugin.tsx
+++ b/x-pack/plugins/lens/server/plugin.tsx
@@ -29,13 +29,13 @@ export class LensServerPlugin implements Plugin<{}, {}, {}, {}> {
   private readonly kibanaIndexConfig: Observable<{ kibana: { index: string } }>;
   private readonly telemetryLogger: Logger;
 
-  constructor(initializerContext: PluginInitializerContext) {
+  constructor(private initializerContext: PluginInitializerContext) {
     this.kibanaIndexConfig = initializerContext.config.legacy.globalConfig$;
     this.telemetryLogger = initializerContext.logger.get('usage');
   }
   setup(core: CoreSetup<PluginStartContract>, plugins: PluginSetupContract) {
     setupSavedObjects(core);
-    setupRoutes(core);
+    setupRoutes(core, this.initializerContext.logger.get());
     if (plugins.usageCollection && plugins.taskManager) {
       registerLensUsageCollector(
         plugins.usageCollection,
diff --git a/x-pack/plugins/lens/server/routes/existing_fields.ts b/x-pack/plugins/lens/server/routes/existing_fields.ts
index c925517b572da..d3b2314a199cb 100644
--- a/x-pack/plugins/lens/server/routes/existing_fields.ts
+++ b/x-pack/plugins/lens/server/routes/existing_fields.ts
@@ -7,10 +7,14 @@
 import Boom from 'boom';
 import { schema } from '@kbn/config-schema';
 import { ILegacyScopedClusterClient, SavedObject, RequestHandlerContext } from 'src/core/server';
-import { CoreSetup } from 'src/core/server';
+import { CoreSetup, Logger } from 'src/core/server';
 import { BASE_API_URL } from '../../common';
 import { IndexPatternAttributes, UI_SETTINGS } from '../../../../../src/plugins/data/server';
 
+export function isBoomError(error: { isBoom?: boolean }): error is Boom {
+  return error.isBoom === true;
+}
+
 /**
  * The number of docs to sample to determine field empty status.
  */
@@ -24,7 +28,7 @@ export interface Field {
   script?: string;
 }
 
-export async function existingFieldsRoute(setup: CoreSetup) {
+export async function existingFieldsRoute(setup: CoreSetup, logger: Logger) {
   const router = setup.http.createRouter();
 
   router.post(
@@ -52,14 +56,17 @@ export async function existingFieldsRoute(setup: CoreSetup) {
           }),
         });
       } catch (e) {
+        logger.info(
+          `Field existence check failed: ${isBoomError(e) ? e.output.payload.message : e.message}`
+        );
         if (e.status === 404) {
-          return res.notFound();
+          return res.notFound({ body: e.message });
         }
-        if (e.isBoom) {
+        if (isBoomError(e)) {
           if (e.output.statusCode === 404) {
-            return res.notFound();
+            return res.notFound({ body: e.output.payload.message });
           }
-          return res.internalError(e.output.message);
+          return res.internalError({ body: e.output.payload.message });
         } else {
           return res.internalError({
             body: Boom.internal(e.message || e.name),
diff --git a/x-pack/plugins/lens/server/routes/index.ts b/x-pack/plugins/lens/server/routes/index.ts
index 8bc04a56e16d5..01018d8cd7fe5 100644
--- a/x-pack/plugins/lens/server/routes/index.ts
+++ b/x-pack/plugins/lens/server/routes/index.ts
@@ -4,13 +4,13 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-import { CoreSetup } from 'src/core/server';
+import { CoreSetup, Logger } from 'src/core/server';
 import { existingFieldsRoute } from './existing_fields';
 import { initFieldsRoute } from './field_stats';
 import { initLensUsageRoute } from './telemetry';
 
-export function setupRoutes(setup: CoreSetup) {
-  existingFieldsRoute(setup);
+export function setupRoutes(setup: CoreSetup, logger: Logger) {
+  existingFieldsRoute(setup, logger);
   initFieldsRoute(setup);
   initLensUsageRoute(setup);
 }
diff --git a/x-pack/plugins/maps/public/actions/layer_actions.ts b/x-pack/plugins/maps/public/actions/layer_actions.ts
index 57f83b9533bda..c8c9f6ba40041 100644
--- a/x-pack/plugins/maps/public/actions/layer_actions.ts
+++ b/x-pack/plugins/maps/public/actions/layer_actions.ts
@@ -441,7 +441,7 @@ export function clearMissingStyleProperties(layerId: string) {
     const {
       hasChanges,
       nextStyleDescriptor,
-    } = (style as IVectorStyle).getDescriptorWithMissingStylePropsRemoved(
+    } = await (style as IVectorStyle).getDescriptorWithMissingStylePropsRemoved(
       nextFields,
       getMapColors(getState())
     );
diff --git a/x-pack/plugins/maps/public/actions/map_actions.ts b/x-pack/plugins/maps/public/actions/map_actions.ts
index 4e76bb24c9e34..f26b00cec9fab 100644
--- a/x-pack/plugins/maps/public/actions/map_actions.ts
+++ b/x-pack/plugins/maps/public/actions/map_actions.ts
@@ -282,12 +282,19 @@ export function setRefreshConfig({ isPaused, interval }: MapRefreshConfig) {
 }
 
 export function triggerRefreshTimer() {
-  return async (dispatch: ThunkDispatch<MapStoreState, void, AnyAction>) => {
+  return async (
+    dispatch: ThunkDispatch<MapStoreState, void, AnyAction>,
+    getState: () => MapStoreState
+  ) => {
     dispatch({
       type: TRIGGER_REFRESH_TIMER,
     });
 
-    await dispatch(syncDataForAllLayers());
+    if (getMapSettings(getState()).autoFitToDataBounds) {
+      dispatch(autoFitToBounds());
+    } else {
+      await dispatch(syncDataForAllLayers());
+    }
   };
 }
 
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/components/vector_style_editor.js b/x-pack/plugins/maps/public/classes/styles/vector/components/vector_style_editor.js
index 53a3fc95adbeb..d577912efb830 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/components/vector_style_editor.js
+++ b/x-pack/plugins/maps/public/classes/styles/vector/components/vector_style_editor.js
@@ -20,20 +20,16 @@ import { i18n } from '@kbn/i18n';
 
 import { EuiSpacer, EuiButtonGroup, EuiFormRow, EuiSwitch } from '@elastic/eui';
 import {
-  CATEGORICAL_DATA_TYPES,
-  ORDINAL_DATA_TYPES,
   LABEL_BORDER_SIZES,
   VECTOR_STYLES,
   STYLE_TYPE,
   VECTOR_SHAPE_TYPE,
 } from '../../../../../common/constants';
+import { createStyleFieldsHelper } from '../style_fields_helper';
 
 export class VectorStyleEditor extends Component {
   state = {
-    dateFields: [],
-    numberFields: [],
-    fields: [],
-    ordinalAndCategoricalFields: [],
+    styleFields: [],
     defaultDynamicProperties: getDefaultDynamicProperties(),
     defaultStaticProperties: getDefaultStaticProperties(),
     supportedFeatures: undefined,
@@ -56,33 +52,17 @@ export class VectorStyleEditor extends Component {
   }
 
   async _loadFields() {
-    const getFieldMeta = async (field) => {
-      return {
-        label: await field.getLabel(),
-        name: field.getName(),
-        origin: field.getOrigin(),
-        type: await field.getDataType(),
-        supportsAutoDomain: field.supportsAutoDomain(),
-      };
-    };
-
-    //These are all fields (only used for text labeling)
-    const fields = await this.props.layer.getStyleEditorFields();
-    const fieldPromises = fields.map(getFieldMeta);
-    const fieldsArrayAll = await Promise.all(fieldPromises);
-    if (!this._isMounted || _.isEqual(fieldsArrayAll, this.state.fields)) {
+    const styleFieldsHelper = await createStyleFieldsHelper(
+      await this.props.layer.getStyleEditorFields()
+    );
+    const styleFields = styleFieldsHelper.getStyleFields();
+    if (!this._isMounted || _.isEqual(styleFields, this.state.styleFields)) {
       return;
     }
 
     this.setState({
-      fields: fieldsArrayAll,
-      ordinalAndCategoricalFields: fieldsArrayAll.filter((field) => {
-        return (
-          CATEGORICAL_DATA_TYPES.includes(field.type) || ORDINAL_DATA_TYPES.includes(field.type)
-        );
-      }),
-      dateFields: fieldsArrayAll.filter((field) => field.type === 'date'),
-      numberFields: fieldsArrayAll.filter((field) => field.type === 'number'),
+      styleFields,
+      styleFieldsHelper,
     });
   }
 
@@ -109,12 +89,6 @@ export class VectorStyleEditor extends Component {
     }
   }
 
-  _getOrdinalFields() {
-    return [...this.state.dateFields, ...this.state.numberFields].filter((field) => {
-      return field.supportsAutoDomain;
-    });
-  }
-
   _handleSelectedFeatureChange = (selectedFeature) => {
     this.setState({ selectedFeature });
   };
@@ -165,7 +139,7 @@ export class VectorStyleEditor extends Component {
         onStaticStyleChange={this._onStaticStyleChange}
         onDynamicStyleChange={this._onDynamicStyleChange}
         styleProperty={this.props.styleProperties[VECTOR_STYLES.FILL_COLOR]}
-        fields={this.state.ordinalAndCategoricalFields}
+        fields={this.state.styleFieldsHelper.getFieldsForStyle(VECTOR_STYLES.FILL_COLOR)}
         defaultStaticStyleOptions={
           this.state.defaultStaticProperties[VECTOR_STYLES.FILL_COLOR].options
         }
@@ -186,7 +160,7 @@ export class VectorStyleEditor extends Component {
         onStaticStyleChange={this._onStaticStyleChange}
         onDynamicStyleChange={this._onDynamicStyleChange}
         styleProperty={this.props.styleProperties[VECTOR_STYLES.LINE_COLOR]}
-        fields={this.state.ordinalAndCategoricalFields}
+        fields={this.state.styleFieldsHelper.getFieldsForStyle(VECTOR_STYLES.LINE_COLOR)}
         defaultStaticStyleOptions={
           this.state.defaultStaticProperties[VECTOR_STYLES.LINE_COLOR].options
         }
@@ -205,7 +179,7 @@ export class VectorStyleEditor extends Component {
         onStaticStyleChange={this._onStaticStyleChange}
         onDynamicStyleChange={this._onDynamicStyleChange}
         styleProperty={this.props.styleProperties[VECTOR_STYLES.LINE_WIDTH]}
-        fields={this._getOrdinalFields()}
+        fields={this.state.styleFieldsHelper.getFieldsForStyle(VECTOR_STYLES.LINE_WIDTH)}
         defaultStaticStyleOptions={
           this.state.defaultStaticProperties[VECTOR_STYLES.LINE_WIDTH].options
         }
@@ -225,7 +199,7 @@ export class VectorStyleEditor extends Component {
           onStaticStyleChange={this._onStaticStyleChange}
           onDynamicStyleChange={this._onDynamicStyleChange}
           styleProperty={this.props.styleProperties[VECTOR_STYLES.LABEL_TEXT]}
-          fields={this.state.fields}
+          fields={this.state.styleFieldsHelper.getFieldsForStyle(VECTOR_STYLES.LABEL_TEXT)}
           defaultStaticStyleOptions={
             this.state.defaultStaticProperties[VECTOR_STYLES.LABEL_TEXT].options
           }
@@ -242,7 +216,7 @@ export class VectorStyleEditor extends Component {
           onStaticStyleChange={this._onStaticStyleChange}
           onDynamicStyleChange={this._onDynamicStyleChange}
           styleProperty={this.props.styleProperties[VECTOR_STYLES.LABEL_COLOR]}
-          fields={this.state.ordinalAndCategoricalFields}
+          fields={this.state.styleFieldsHelper.getFieldsForStyle(VECTOR_STYLES.LABEL_COLOR)}
           defaultStaticStyleOptions={
             this.state.defaultStaticProperties[VECTOR_STYLES.LABEL_COLOR].options
           }
@@ -258,7 +232,7 @@ export class VectorStyleEditor extends Component {
           onStaticStyleChange={this._onStaticStyleChange}
           onDynamicStyleChange={this._onDynamicStyleChange}
           styleProperty={this.props.styleProperties[VECTOR_STYLES.LABEL_SIZE]}
-          fields={this._getOrdinalFields()}
+          fields={this.state.styleFieldsHelper.getFieldsForStyle(VECTOR_STYLES.LABEL_SIZE)}
           defaultStaticStyleOptions={
             this.state.defaultStaticProperties[VECTOR_STYLES.LABEL_SIZE].options
           }
@@ -275,7 +249,7 @@ export class VectorStyleEditor extends Component {
           onStaticStyleChange={this._onStaticStyleChange}
           onDynamicStyleChange={this._onDynamicStyleChange}
           styleProperty={this.props.styleProperties[VECTOR_STYLES.LABEL_BORDER_COLOR]}
-          fields={this.state.ordinalAndCategoricalFields}
+          fields={this.state.styleFieldsHelper.getFieldsForStyle(VECTOR_STYLES.LABEL_BORDER_COLOR)}
           defaultStaticStyleOptions={
             this.state.defaultStaticProperties[VECTOR_STYLES.LABEL_BORDER_COLOR].options
           }
@@ -309,7 +283,7 @@ export class VectorStyleEditor extends Component {
             onStaticStyleChange={this._onStaticStyleChange}
             onDynamicStyleChange={this._onDynamicStyleChange}
             styleProperty={this.props.styleProperties[VECTOR_STYLES.ICON_ORIENTATION]}
-            fields={this.state.numberFields}
+            fields={this.state.styleFieldsHelper.getFieldsForStyle(VECTOR_STYLES.ICON_ORIENTATION)}
             defaultStaticStyleOptions={
               this.state.defaultStaticProperties[VECTOR_STYLES.ICON_ORIENTATION].options
             }
@@ -328,7 +302,7 @@ export class VectorStyleEditor extends Component {
             onStaticStyleChange={this._onStaticStyleChange}
             onDynamicStyleChange={this._onDynamicStyleChange}
             styleProperty={this.props.styleProperties[VECTOR_STYLES.ICON]}
-            fields={this.state.ordinalAndCategoricalFields}
+            fields={this.state.styleFieldsHelper.getFieldsForStyle(VECTOR_STYLES.ICON)}
             defaultStaticStyleOptions={
               this.state.defaultStaticProperties[VECTOR_STYLES.ICON].options
             }
@@ -368,7 +342,7 @@ export class VectorStyleEditor extends Component {
           onStaticStyleChange={this._onStaticStyleChange}
           onDynamicStyleChange={this._onDynamicStyleChange}
           styleProperty={this.props.styleProperties[VECTOR_STYLES.ICON_SIZE]}
-          fields={this._getOrdinalFields()}
+          fields={this.state.styleFieldsHelper.getFieldsForStyle(VECTOR_STYLES.ICON_SIZE)}
           defaultStaticStyleOptions={
             this.state.defaultStaticProperties[VECTOR_STYLES.ICON_SIZE].options
           }
@@ -409,9 +383,9 @@ export class VectorStyleEditor extends Component {
   }
 
   _renderProperties() {
-    const { supportedFeatures, selectedFeature } = this.state;
+    const { supportedFeatures, selectedFeature, styleFieldsHelper } = this.state;
 
-    if (!supportedFeatures) {
+    if (!supportedFeatures || !styleFieldsHelper) {
       return null;
     }
 
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/__tests__/test_util.ts b/x-pack/plugins/maps/public/classes/styles/vector/properties/__tests__/test_util.ts
index a2dfdc94d8058..a3f63ba7717ea 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/properties/__tests__/test_util.ts
+++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/__tests__/test_util.ts
@@ -16,10 +16,38 @@ import {
 import { AbstractField, IField } from '../../../../fields/field';
 import { IStyle } from '../../../style';
 
-class MockField extends AbstractField {
+export class MockField extends AbstractField {
+  private readonly _dataType: string;
+  private readonly _supportsAutoDomain: boolean;
+
+  constructor({
+    fieldName,
+    origin = FIELD_ORIGIN.SOURCE,
+    dataType = 'string',
+    supportsAutoDomain = true,
+  }: {
+    fieldName: string;
+    origin?: FIELD_ORIGIN;
+    dataType?: string;
+    supportsAutoDomain?: boolean;
+  }) {
+    super({ fieldName, origin });
+    this._dataType = dataType;
+    this._supportsAutoDomain = supportsAutoDomain;
+  }
+
   async getLabel(): Promise<string> {
     return this.getName() + '_label';
   }
+
+  async getDataType(): Promise<string> {
+    return this._dataType;
+  }
+
+  supportsAutoDomain(): boolean {
+    return this._supportsAutoDomain;
+  }
+
   supportsFieldMeta(): boolean {
     return true;
   }
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/style_fields_helper.ts b/x-pack/plugins/maps/public/classes/styles/vector/style_fields_helper.ts
new file mode 100644
index 0000000000000..8613f9e1e946f
--- /dev/null
+++ b/x-pack/plugins/maps/public/classes/styles/vector/style_fields_helper.ts
@@ -0,0 +1,96 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import {
+  CATEGORICAL_DATA_TYPES,
+  FIELD_ORIGIN,
+  ORDINAL_DATA_TYPES,
+  VECTOR_STYLES,
+} from '../../../../common/constants';
+import { IField } from '../../fields/field';
+
+export interface StyleField {
+  label: string;
+  name: string;
+  origin: FIELD_ORIGIN;
+  type: string;
+  supportsAutoDomain: boolean;
+}
+
+export async function createStyleFieldsHelper(fields: IField[]): Promise<StyleFieldsHelper> {
+  const promises: Array<Promise<StyleField>> = fields.map(async (field: IField) => {
+    return {
+      label: await field.getLabel(),
+      name: field.getName(),
+      origin: field.getOrigin(),
+      type: await field.getDataType(),
+      supportsAutoDomain: field.supportsAutoDomain(),
+    };
+  });
+  const styleFields = await Promise.all(promises);
+  return new StyleFieldsHelper(styleFields);
+}
+
+class StyleFieldsHelper {
+  private readonly _styleFields: StyleField[];
+  private readonly _ordinalAndCategoricalFields: StyleField[];
+  private readonly _numberFields: StyleField[];
+  private readonly _ordinalFields: StyleField[];
+
+  constructor(styleFields: StyleField[]) {
+    const ordinalAndCategoricalFields: StyleField[] = [];
+    const numberFields: StyleField[] = [];
+    const ordinalFields: StyleField[] = [];
+
+    styleFields.forEach((styleField: StyleField) => {
+      if (
+        CATEGORICAL_DATA_TYPES.includes(styleField.type) ||
+        ORDINAL_DATA_TYPES.includes(styleField.type)
+      ) {
+        ordinalAndCategoricalFields.push(styleField);
+      }
+
+      if (styleField.type === 'date' || styleField.type === 'number') {
+        if (styleField.type === 'number') {
+          numberFields.push(styleField);
+        }
+        if (styleField.supportsAutoDomain) {
+          ordinalFields.push(styleField);
+        }
+      }
+    });
+
+    this._styleFields = styleFields;
+    this._ordinalAndCategoricalFields = ordinalAndCategoricalFields;
+    this._numberFields = numberFields;
+    this._ordinalFields = ordinalFields;
+  }
+
+  getFieldsForStyle(styleName: VECTOR_STYLES): StyleField[] {
+    switch (styleName) {
+      case VECTOR_STYLES.ICON_ORIENTATION:
+        return this._numberFields;
+      case VECTOR_STYLES.FILL_COLOR:
+      case VECTOR_STYLES.LINE_COLOR:
+      case VECTOR_STYLES.LABEL_COLOR:
+      case VECTOR_STYLES.LABEL_BORDER_COLOR:
+      case VECTOR_STYLES.ICON:
+        return this._ordinalAndCategoricalFields;
+      case VECTOR_STYLES.LINE_WIDTH:
+      case VECTOR_STYLES.LABEL_SIZE:
+      case VECTOR_STYLES.ICON_SIZE:
+        return this._ordinalFields;
+      case VECTOR_STYLES.LABEL_TEXT:
+        return this._styleFields;
+      default:
+        return [];
+    }
+  }
+
+  getStyleFields(): StyleField[] {
+    return this._styleFields;
+  }
+}
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.test.js b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.test.js
index 28801a402ca14..1dbadc054c8a0 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.test.js
+++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.test.js
@@ -12,23 +12,10 @@ import {
   VECTOR_SHAPE_TYPE,
   VECTOR_STYLES,
 } from '../../../../common/constants';
+import { MockField } from './properties/__tests__/test_util';
 
 jest.mock('../../../kibana_services');
 
-class MockField {
-  constructor({ fieldName }) {
-    this._fieldName = fieldName;
-  }
-
-  getName() {
-    return this._fieldName;
-  }
-
-  isValid() {
-    return !!this._fieldName;
-  }
-}
-
 class MockSource {
   constructor({ supportedShapeTypes } = {}) {
     this._supportedShapeTypes = supportedShapeTypes || Object.values(VECTOR_SHAPE_TYPE);
@@ -77,25 +64,25 @@ describe('getDescriptorWithMissingStylePropsRemoved', () => {
     });
   });
 
-  it('Should return no changes when next ordinal fields contain existing style property fields', () => {
+  it('Should return no changes when next ordinal fields contain existing style property fields', async () => {
     const vectorStyle = new VectorStyle({ properties }, new MockSource());
 
-    const nextFields = [new MockField({ fieldName })];
-    const { hasChanges } = vectorStyle.getDescriptorWithMissingStylePropsRemoved(
+    const nextFields = [new MockField({ fieldName, dataType: 'number' })];
+    const { hasChanges } = await vectorStyle.getDescriptorWithMissingStylePropsRemoved(
       nextFields,
       mapColors
     );
     expect(hasChanges).toBe(false);
   });
 
-  it('Should clear missing fields when next ordinal fields do not contain existing style property fields', () => {
+  it('Should clear missing fields when next ordinal fields do not contain existing style property fields', async () => {
     const vectorStyle = new VectorStyle({ properties }, new MockSource());
 
-    const nextFields = [new MockField({ fieldName: 'someOtherField' })];
+    const nextFields = [new MockField({ fieldName: 'someOtherField', dataType: 'number' })];
     const {
       hasChanges,
       nextStyleDescriptor,
-    } = vectorStyle.getDescriptorWithMissingStylePropsRemoved(nextFields, mapColors);
+    } = await vectorStyle.getDescriptorWithMissingStylePropsRemoved(nextFields, mapColors);
     expect(hasChanges).toBe(true);
     expect(nextStyleDescriptor.properties[VECTOR_STYLES.LINE_COLOR]).toEqual({
       options: {},
@@ -110,14 +97,14 @@ describe('getDescriptorWithMissingStylePropsRemoved', () => {
     });
   });
 
-  it('Should convert dynamic styles to static styles when there are no next fields', () => {
+  it('Should convert dynamic styles to static styles when there are no next fields', async () => {
     const vectorStyle = new VectorStyle({ properties }, new MockSource());
 
     const nextFields = [];
     const {
       hasChanges,
       nextStyleDescriptor,
-    } = vectorStyle.getDescriptorWithMissingStylePropsRemoved(nextFields, mapColors);
+    } = await vectorStyle.getDescriptorWithMissingStylePropsRemoved(nextFields, mapColors);
     expect(hasChanges).toBe(true);
     expect(nextStyleDescriptor.properties[VECTOR_STYLES.LINE_COLOR]).toEqual({
       options: {
@@ -132,6 +119,25 @@ describe('getDescriptorWithMissingStylePropsRemoved', () => {
       type: 'STATIC',
     });
   });
+
+  it('Should convert dynamic ICON_SIZE static style when there are no next ordinal fields', async () => {
+    const vectorStyle = new VectorStyle({ properties }, new MockSource());
+
+    const nextFields = [
+      new MockField({ fieldName, dataType: 'number', supportsAutoDomain: false }),
+    ];
+    const {
+      hasChanges,
+      nextStyleDescriptor,
+    } = await vectorStyle.getDescriptorWithMissingStylePropsRemoved(nextFields, mapColors);
+    expect(hasChanges).toBe(true);
+    expect(nextStyleDescriptor.properties[VECTOR_STYLES.ICON_SIZE]).toEqual({
+      options: {
+        size: 6,
+      },
+      type: 'STATIC',
+    });
+  });
 });
 
 describe('pluckStyleMetaFromSourceDataRequest', () => {
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx
index acb158636e0b3..5d360f5452d36 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx
+++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx
@@ -77,6 +77,7 @@ import { IField } from '../../fields/field';
 import { IVectorLayer } from '../../layers/vector_layer/vector_layer';
 import { IVectorSource } from '../../sources/vector_source';
 import { ILayer } from '../../layers/layer';
+import { createStyleFieldsHelper } from './style_fields_helper';
 
 const POINTS = [GEO_JSON_TYPE.POINT, GEO_JSON_TYPE.MULTI_POINT];
 const LINES = [GEO_JSON_TYPE.LINE_STRING, GEO_JSON_TYPE.MULTI_LINE_STRING];
@@ -90,7 +91,7 @@ export interface IVectorStyle extends IStyle {
   getDescriptorWithMissingStylePropsRemoved(
     nextFields: IField[],
     mapColors: string[]
-  ): { hasChanges: boolean; nextStyleDescriptor?: VectorStyleDescriptor };
+  ): Promise<{ hasChanges: boolean; nextStyleDescriptor?: VectorStyleDescriptor }>;
   pluckStyleMetaFromSourceDataRequest(sourceDataRequest: DataRequest): Promise<StyleMetaDescriptor>;
   isTimeAware: () => boolean;
   getIcon: () => ReactElement<any>;
@@ -324,7 +325,8 @@ export class VectorStyle implements IVectorStyle {
    * This method does not update its descriptor. It just returns a new descriptor that the caller
    * can then use to update store state via dispatch.
    */
-  getDescriptorWithMissingStylePropsRemoved(nextFields: IField[], mapColors: string[]) {
+  async getDescriptorWithMissingStylePropsRemoved(nextFields: IField[], mapColors: string[]) {
+    const styleFieldsHelper = await createStyleFieldsHelper(nextFields);
     const originalProperties = this.getRawProperties();
     const updatedProperties = {} as VectorStylePropertiesDescriptor;
 
@@ -346,8 +348,9 @@ export class VectorStyle implements IVectorStyle {
     });
 
     dynamicProperties.forEach((key: VECTOR_STYLES) => {
-      // Convert dynamic styling to static stying when there are no nextFields
-      if (nextFields.length === 0) {
+      // Convert dynamic styling to static stying when there are no style fields
+      const styleFields = styleFieldsHelper.getFieldsForStyle(key);
+      if (styleFields.length === 0) {
         const staticProperties = getDefaultStaticProperties(mapColors);
         updatedProperties[key] = staticProperties[key] as any;
         return;
diff --git a/x-pack/plugins/maps/public/connected_components/map_settings_panel/__snapshots__/navigation_panel.test.tsx.snap b/x-pack/plugins/maps/public/connected_components/map_settings_panel/__snapshots__/navigation_panel.test.tsx.snap
index a617fbc552854..1859c7d8177f8 100644
--- a/x-pack/plugins/maps/public/connected_components/map_settings_panel/__snapshots__/navigation_panel.test.tsx.snap
+++ b/x-pack/plugins/maps/public/connected_components/map_settings_panel/__snapshots__/navigation_panel.test.tsx.snap
@@ -25,7 +25,7 @@ exports[`should render 1`] = `
     labelType="label"
   >
     <EuiSwitch
-      checked={true}
+      checked={false}
       compressed={true}
       data-test-subj="autoFitToDataBoundsSwitch"
       label="Auto fit map to data bounds"
@@ -119,7 +119,7 @@ exports[`should render browser location form when initialLocation is BROWSER_LOC
     labelType="label"
   >
     <EuiSwitch
-      checked={true}
+      checked={false}
       compressed={true}
       data-test-subj="autoFitToDataBoundsSwitch"
       label="Auto fit map to data bounds"
@@ -233,7 +233,7 @@ exports[`should render fixed location form when initialLocation is FIXED_LOCATIO
     labelType="label"
   >
     <EuiSwitch
-      checked={true}
+      checked={false}
       compressed={true}
       data-test-subj="autoFitToDataBoundsSwitch"
       label="Auto fit map to data bounds"
diff --git a/x-pack/plugins/maps/public/reducers/default_map_settings.ts b/x-pack/plugins/maps/public/reducers/default_map_settings.ts
index 5375b5ca5c59b..896ac11e36782 100644
--- a/x-pack/plugins/maps/public/reducers/default_map_settings.ts
+++ b/x-pack/plugins/maps/public/reducers/default_map_settings.ts
@@ -9,7 +9,7 @@ import { MapSettings } from './map';
 
 export function getDefaultMapSettings(): MapSettings {
   return {
-    autoFitToDataBounds: true,
+    autoFitToDataBounds: false,
     initialLocation: INITIAL_LOCATION.LAST_SAVED_LOCATION,
     fixedLocation: { lat: 0, lon: 0, zoom: 2 },
     browserLocation: { zoom: 2 },
diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/get_breadcrumbs.tsx b/x-pack/plugins/maps/public/routing/routes/maps_app/get_breadcrumbs.tsx
index 1f74b0d6d1449..d9b60b670b93e 100644
--- a/x-pack/plugins/maps/public/routing/routes/maps_app/get_breadcrumbs.tsx
+++ b/x-pack/plugins/maps/public/routing/routes/maps_app/get_breadcrumbs.tsx
@@ -5,17 +5,21 @@
  */
 
 import { i18n } from '@kbn/i18n';
-import { getNavigateToApp } from '../../../kibana_services';
+import { getCoreOverlays, getNavigateToApp } from '../../../kibana_services';
 import { goToSpecifiedPath } from '../../maps_router';
 import { getAppTitle } from '../../../../common/i18n_getters';
 
 export const unsavedChangesWarning = i18n.translate(
   'xpack.maps.breadCrumbs.unsavedChangesWarning',
   {
-    defaultMessage: 'Your map has unsaved changes. Are you sure you want to leave?',
+    defaultMessage: 'Leave Maps with unsaved work?',
   }
 );
 
+export const unsavedChangesTitle = i18n.translate('xpack.maps.breadCrumbs.unsavedChangesTitle', {
+  defaultMessage: 'Unsaved changes',
+});
+
 export function getBreadcrumbs({
   title,
   getHasUnsavedChanges,
@@ -39,10 +43,13 @@ export function getBreadcrumbs({
 
   breadcrumbs.push({
     text: getAppTitle(),
-    onClick: () => {
+    onClick: async () => {
       if (getHasUnsavedChanges()) {
-        const navigateAway = window.confirm(unsavedChangesWarning);
-        if (navigateAway) {
+        const confirmed = await getCoreOverlays().openConfirm(unsavedChangesWarning, {
+          title: unsavedChangesTitle,
+          'data-test-subj': 'appLeaveConfirmModal',
+        });
+        if (confirmed) {
           goToSpecifiedPath('/');
         }
       } else {
diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.tsx b/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.tsx
index bd08b2f11fadc..df46d5d6a13ff 100644
--- a/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.tsx
+++ b/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.tsx
@@ -43,7 +43,7 @@ import {
 import { MapContainer } from '../../../connected_components/map_container';
 import { getIndexPatternsFromIds } from '../../../index_pattern_util';
 import { getTopNavConfig } from './top_nav_config';
-import { getBreadcrumbs, unsavedChangesWarning } from './get_breadcrumbs';
+import { getBreadcrumbs, unsavedChangesTitle, unsavedChangesWarning } from './get_breadcrumbs';
 import {
   LayerDescriptor,
   MapRefreshConfig,
@@ -138,9 +138,7 @@ export class MapsAppView extends React.Component<Props, State> {
 
     this.props.onAppLeave((actions) => {
       if (this._hasUnsavedChanges()) {
-        if (!window.confirm(unsavedChangesWarning)) {
-          return {} as AppLeaveAction;
-        }
+        return actions.confirm(unsavedChangesWarning, unsavedChangesTitle);
       }
       return actions.default() as AppLeaveAction;
     });
diff --git a/x-pack/plugins/maps/server/routes.js b/x-pack/plugins/maps/server/routes.js
index 6b19103b59722..5feacfee4d4d2 100644
--- a/x-pack/plugins/maps/server/routes.js
+++ b/x-pack/plugins/maps/server/routes.js
@@ -189,18 +189,28 @@ export function initRoutes(router, licenseUid, mapConfig, kbnVersion, logger) {
         return badRequest('map.proxyElasticMapsServiceInMaps disabled');
       }
 
-      const file = await emsClient.getDefaultFileManifest();
-      const layers = file.layers.map((layer) => {
-        const newLayer = { ...layer };
-        const id = encodeURIComponent(layer.layer_id);
+      const file = await emsClient.getDefaultFileManifest(); //need raw manifest
+      const fileLayers = await emsClient.getFileLayers();
+
+      const layers = file.layers.map((layerJson) => {
+        const newLayerJson = { ...layerJson };
+        const id = encodeURIComponent(layerJson.layer_id);
+
+        const fileLayer = fileLayers.find((fileLayer) => fileLayer.getId() === layerJson.layer_id);
+        const defaultFormat = layerJson.formats.find(
+          (format) => format.type === fileLayer.getDefaultFormatType()
+        );
+
         const newUrl = `${EMS_FILES_DEFAULT_JSON_PATH}?id=${id}`;
-        newLayer.formats = [
+
+        //Only proxy default-format. Others are unused in Maps-app
+        newLayerJson.formats = [
           {
-            ...layer.formats[0],
+            ...defaultFormat,
             url: newUrl,
           },
         ];
-        return newLayer;
+        return newLayerJson;
       });
       //rewrite
       return ok({
diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer.scss b/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer.scss
index 8d4f6ad0a6844..45678f6e71c2e 100644
--- a/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer.scss
+++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer.scss
@@ -24,10 +24,6 @@
     }
   }
 
-  .single-metric-request-callout {
-    margin: 0 $euiSize;
-  }
-
   .results-container {
     .panel-title {
       font-size: $euiFontSizeM;
diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/entity_control/entity_control.tsx b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/entity_control/entity_control.tsx
index 9d2c49a95fec4..e1323019d61db 100644
--- a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/entity_control/entity_control.tsx
+++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/entity_control/entity_control.tsx
@@ -9,13 +9,7 @@ import React, { Component } from 'react';
 import { FormattedMessage } from '@kbn/i18n/react';
 import { i18n } from '@kbn/i18n';
 
-import {
-  EuiComboBox,
-  EuiComboBoxOptionOption,
-  EuiFlexItem,
-  EuiFormRow,
-  EuiToolTip,
-} from '@elastic/eui';
+import { EuiComboBox, EuiComboBoxOptionOption, EuiFlexItem, EuiFormRow } from '@elastic/eui';
 
 export interface Entity {
   fieldName: string;
@@ -156,9 +150,7 @@ export class EntityControl extends Component<EntityControlProps, EntityControlSt
     return (
       <EuiFlexItem grow={false}>
         <EuiFormRow label={entity.fieldName} helpText={forceSelection ? selectMessage : null}>
-          <EuiToolTip position="right" content={forceSelection ? selectMessage : null}>
-            {control}
-          </EuiToolTip>
+          {control}
         </EuiFormRow>
       </EuiFlexItem>
     );
diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js
index 7d173e161a1cb..9b8764d3f9279 100644
--- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js
+++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js
@@ -1133,23 +1133,25 @@ export class TimeSeriesExplorer extends React.Component {
     return (
       <TimeSeriesExplorerPage dateFormatTz={dateFormatTz} resizeRef={this.resizeRef}>
         {fieldNamesWithEmptyValues.length > 0 && (
-          <EuiCallOut
-            className="single-metric-request-callout"
-            title={
-              <FormattedMessage
-                id="xpack.ml.timeSeriesExplorer.singleMetricRequiredMessage"
-                defaultMessage="To view a single metric you must select {missingValuesCount, plural, one {a value for {fieldName1}} other {values for {fieldName1} and {fieldName2}}}"
-                values={{
-                  missingValuesCount: fieldNamesWithEmptyValues.length,
-                  fieldName1: fieldNamesWithEmptyValues[0],
-                  fieldName2: fieldNamesWithEmptyValues[1],
-                }}
-              />
-            }
-            color="warning"
-            iconType="help"
-            size="s"
-          />
+          <>
+            <EuiCallOut
+              title={
+                <FormattedMessage
+                  id="xpack.ml.timeSeriesExplorer.singleMetricRequiredMessage"
+                  defaultMessage="To view a single metric you must select {missingValuesCount, plural, one {a value for {fieldName1}} other {values for {fieldName1} and {fieldName2}}}"
+                  values={{
+                    missingValuesCount: fieldNamesWithEmptyValues.length,
+                    fieldName1: fieldNamesWithEmptyValues[0],
+                    fieldName2: fieldNamesWithEmptyValues[1],
+                  }}
+                />
+              }
+              color="warning"
+              iconType="help"
+              size="s"
+            />
+            <EuiSpacer size="m" />
+          </>
         )}
 
         <div className="series-controls" data-test-subj="mlSingleMetricViewerSeriesControls">
diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/node/advanced.js b/x-pack/plugins/monitoring/public/components/elasticsearch/node/advanced.js
index b2a17515bbb96..67df745e619d4 100644
--- a/x-pack/plugins/monitoring/public/components/elasticsearch/node/advanced.js
+++ b/x-pack/plugins/monitoring/public/components/elasticsearch/node/advanced.js
@@ -18,8 +18,9 @@ import {
 import { NodeDetailStatus } from '../node_detail_status';
 import { MonitoringTimeseriesContainer } from '../../chart';
 import { FormattedMessage } from '@kbn/i18n/react';
+import { AlertsCallout } from '../../../alerts/callout';
 
-export const AdvancedNode = ({ nodeSummary, metrics, alerts, ...props }) => {
+export const AdvancedNode = ({ nodeSummary, metrics, alerts, nodeId, ...props }) => {
   const metricsToShow = [
     metrics.node_gc,
     metrics.node_gc_time,
@@ -50,9 +51,25 @@ export const AdvancedNode = ({ nodeSummary, metrics, alerts, ...props }) => {
           </h1>
         </EuiScreenReaderOnly>
         <EuiPanel>
-          <NodeDetailStatus stats={nodeSummary} alerts={alerts} />
+          <NodeDetailStatus
+            stats={nodeSummary}
+            alerts={alerts}
+            alertsStateFilter={(state) =>
+              state.nodeId === nodeId || state.stackProductUuid === nodeId
+            }
+          />
         </EuiPanel>
         <EuiSpacer size="m" />
+        <AlertsCallout
+          alerts={alerts}
+          stateFilter={(state) => state.nodeId === nodeId || state.stackProductUuid === nodeId}
+          nextStepsFilter={(nextStep) => {
+            if (nextStep.text.includes('Elasticsearch nodes')) {
+              return false;
+            }
+            return true;
+          }}
+        />
         <EuiPageContent>
           <EuiFlexGrid columns={2} gutterSize="s">
             {metricsToShow.map((metric, index) => (
diff --git a/x-pack/plugins/monitoring/public/views/elasticsearch/node/advanced/index.js b/x-pack/plugins/monitoring/public/views/elasticsearch/node/advanced/index.js
index 03c0714864f92..8021ae7e5f63c 100644
--- a/x-pack/plugins/monitoring/public/views/elasticsearch/node/advanced/index.js
+++ b/x-pack/plugins/monitoring/public/views/elasticsearch/node/advanced/index.js
@@ -117,6 +117,7 @@ uiRoutes.when('/elasticsearch/nodes/:node/advanced', {
             <AdvancedNode
               nodeSummary={data.nodeSummary}
               alerts={this.alerts}
+              nodeId={data.nodeSummary.resolver}
               metrics={data.metrics}
               onBrush={this.onBrush}
               zoomInfo={this.zoomInfo}
diff --git a/x-pack/plugins/monitoring/server/alerts/cpu_usage_alert.ts b/x-pack/plugins/monitoring/server/alerts/cpu_usage_alert.ts
index 3117a160ecb62..09133dadca162 100644
--- a/x-pack/plugins/monitoring/server/alerts/cpu_usage_alert.ts
+++ b/x-pack/plugins/monitoring/server/alerts/cpu_usage_alert.ts
@@ -106,18 +106,15 @@ export class CpuUsageAlert extends BaseAlert {
       this.config.ui.max_bucket_size
     );
     return stats.map((stat) => {
-      let cpuUsage = 0;
       if (this.config.ui.container.elasticsearch.enabled) {
-        cpuUsage =
+        stat.cpuUsage =
           (stat.containerUsage / (stat.containerPeriods * stat.containerQuota * 1000)) * 100;
-      } else {
-        cpuUsage = stat.cpuUsage;
       }
 
       return {
         instanceKey: `${stat.clusterUuid}:${stat.nodeId}`,
         clusterUuid: stat.clusterUuid,
-        shouldFire: cpuUsage > params.threshold,
+        shouldFire: stat.cpuUsage > params.threshold,
         severity: AlertSeverity.Danger,
         meta: stat,
         ccs: stat.ccs,
diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_settings_collector.ts b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_settings_collector.ts
index a3ff4b952ce97..0dd5ce291f972 100644
--- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_settings_collector.ts
+++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_settings_collector.ts
@@ -4,7 +4,7 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-import { Collector } from '../../../../../../src/plugins/usage_collection/server';
+import { Collector, UsageCollectionSetup } from 'src/plugins/usage_collection/server';
 
 import { KIBANA_SETTINGS_TYPE } from '../../../common/constants';
 import { MonitoringConfig } from '../../config';
@@ -48,10 +48,18 @@ export interface KibanaSettingsCollector extends Collector<EmailSettingData | un
   getEmailValueStructure(email: string | null): EmailSettingData;
 }
 
-export function getSettingsCollector(usageCollection: any, config: MonitoringConfig) {
+export function getSettingsCollector(
+  usageCollection: UsageCollectionSetup,
+  config: MonitoringConfig
+) {
   return usageCollection.makeStatsCollector({
     type: KIBANA_SETTINGS_TYPE,
     isReady: () => true,
+    schema: {
+      xpack: {
+        default_admin_email: { type: 'text' },
+      },
+    },
     async fetch(this: KibanaSettingsCollector) {
       let kibanaSettingsData;
       const defaultAdminEmail = await checkForEmailValue(config);
diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.test.ts
index 12926a30efa1b..88035c1121848 100644
--- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.test.ts
+++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.test.ts
@@ -97,11 +97,18 @@ describe('fetchCpuUsageNodeStats', () => {
                           },
                         ],
                       },
-                      average_usage: {
-                        value: 10,
-                      },
-                      average_periods: {
-                        value: 5,
+                      histo: {
+                        buckets: [
+                          null,
+                          {
+                            usage_deriv: {
+                              normalized_value: 10,
+                            },
+                            periods_deriv: {
+                              normalized_value: 5,
+                            },
+                          },
+                        ],
                       },
                       average_quota: {
                         value: 50,
@@ -185,14 +192,14 @@ describe('fetchCpuUsageNodeStats', () => {
     });
     await fetchCpuUsageNodeStats(callCluster, clusters, index, startMs, endMs, size);
     expect(params).toStrictEqual({
-      index,
+      index: '.monitoring-es-*',
       filterPath: ['aggregations'],
       body: {
         size: 0,
         query: {
           bool: {
             filter: [
-              { terms: { cluster_uuid: clusters.map((cluster) => cluster.clusterUuid) } },
+              { terms: { cluster_uuid: ['abc123'] } },
               { term: { type: 'node_stats' } },
               { range: { timestamp: { format: 'epoch_millis', gte: 0, lte: 0 } } },
             ],
@@ -200,23 +207,38 @@ describe('fetchCpuUsageNodeStats', () => {
         },
         aggs: {
           clusters: {
-            terms: {
-              field: 'cluster_uuid',
-              size,
-              include: clusters.map((cluster) => cluster.clusterUuid),
-            },
+            terms: { field: 'cluster_uuid', size: 10, include: ['abc123'] },
             aggs: {
               nodes: {
-                terms: { field: 'node_stats.node_id', size },
+                terms: { field: 'node_stats.node_id', size: 10 },
                 aggs: {
                   index: { terms: { field: '_index', size: 1 } },
                   average_cpu: { avg: { field: 'node_stats.process.cpu.percent' } },
-                  average_usage: { avg: { field: 'node_stats.os.cgroup.cpuacct.usage_nanos' } },
-                  average_periods: {
-                    avg: { field: 'node_stats.os.cgroup.cpu.stat.number_of_elapsed_periods' },
-                  },
                   average_quota: { avg: { field: 'node_stats.os.cgroup.cpu.cfs_quota_micros' } },
                   name: { terms: { field: 'source_node.name', size: 1 } },
+                  histo: {
+                    date_histogram: { field: 'timestamp', fixed_interval: '0m' },
+                    aggs: {
+                      average_periods: {
+                        max: { field: 'node_stats.os.cgroup.cpu.stat.number_of_elapsed_periods' },
+                      },
+                      average_usage: { max: { field: 'node_stats.os.cgroup.cpuacct.usage_nanos' } },
+                      usage_deriv: {
+                        derivative: {
+                          buckets_path: 'average_usage',
+                          gap_policy: 'skip',
+                          unit: '1s',
+                        },
+                      },
+                      periods_deriv: {
+                        derivative: {
+                          buckets_path: 'average_periods',
+                          gap_policy: 'skip',
+                          unit: '1s',
+                        },
+                      },
+                    },
+                  },
                 },
               },
             },
diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.ts
index 4fdb03b61950e..ecd324c083a8c 100644
--- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.ts
+++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.ts
@@ -4,6 +4,8 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 import { get } from 'lodash';
+import moment from 'moment';
+import { NORMALIZED_DERIVATIVE_UNIT } from '../../../common/constants';
 import { AlertCluster, AlertCpuUsageNodeStats } from '../../alerts/types';
 
 interface NodeBucketESResponse {
@@ -26,6 +28,9 @@ export async function fetchCpuUsageNodeStats(
   endMs: number,
   size: number
 ): Promise<AlertCpuUsageNodeStats[]> {
+  // Using pure MS didn't seem to work well with the date_histogram interval
+  // but minutes does
+  const intervalInMinutes = moment.duration(endMs - startMs).asMinutes();
   const filterPath = ['aggregations'];
   const params = {
     index,
@@ -82,16 +87,6 @@ export async function fetchCpuUsageNodeStats(
                     field: 'node_stats.process.cpu.percent',
                   },
                 },
-                average_usage: {
-                  avg: {
-                    field: 'node_stats.os.cgroup.cpuacct.usage_nanos',
-                  },
-                },
-                average_periods: {
-                  avg: {
-                    field: 'node_stats.os.cgroup.cpu.stat.number_of_elapsed_periods',
-                  },
-                },
                 average_quota: {
                   avg: {
                     field: 'node_stats.os.cgroup.cpu.cfs_quota_micros',
@@ -103,6 +98,38 @@ export async function fetchCpuUsageNodeStats(
                     size: 1,
                   },
                 },
+                histo: {
+                  date_histogram: {
+                    field: 'timestamp',
+                    fixed_interval: `${intervalInMinutes}m`,
+                  },
+                  aggs: {
+                    average_periods: {
+                      max: {
+                        field: 'node_stats.os.cgroup.cpu.stat.number_of_elapsed_periods',
+                      },
+                    },
+                    average_usage: {
+                      max: {
+                        field: 'node_stats.os.cgroup.cpuacct.usage_nanos',
+                      },
+                    },
+                    usage_deriv: {
+                      derivative: {
+                        buckets_path: 'average_usage',
+                        gap_policy: 'skip',
+                        unit: NORMALIZED_DERIVATIVE_UNIT,
+                      },
+                    },
+                    periods_deriv: {
+                      derivative: {
+                        buckets_path: 'average_periods',
+                        gap_policy: 'skip',
+                        unit: NORMALIZED_DERIVATIVE_UNIT,
+                      },
+                    },
+                  },
+                },
               },
             },
           },
@@ -120,17 +147,19 @@ export async function fetchCpuUsageNodeStats(
   ) as ClusterBucketESResponse[];
   for (const clusterBucket of clusterBuckets) {
     for (const node of clusterBucket.nodes.buckets) {
+      const lastBucket = get(node, 'histo.buckets[1]', {});
       const indexName = get(node, 'index.buckets[0].key', '');
-      stats.push({
+      const stat = {
         clusterUuid: clusterBucket.key,
         nodeId: node.key,
         nodeName: get(node, 'name.buckets[0].key'),
         cpuUsage: get(node, 'average_cpu.value'),
-        containerUsage: get(node, 'average_usage.value'),
-        containerPeriods: get(node, 'average_periods.value'),
+        containerUsage: get(lastBucket, 'usage_deriv.normalized_value'),
+        containerPeriods: get(lastBucket, 'periods_deriv.normalized_value'),
         containerQuota: get(node, 'average_quota.value'),
         ccs: indexName.includes(':') ? indexName.split(':')[0] : null,
-      });
+      };
+      stats.push(stat);
     }
   }
   return stats;
diff --git a/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx b/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx
index 7782576bb5a00..1e3f7e34bebdb 100644
--- a/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx
+++ b/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx
@@ -108,7 +108,7 @@ export class GetCsvReportPanelAction implements ActionDefinition<ActionContext>
     const filename = embeddable.getSavedSearch().title;
     const timezone = kibanaTimezone === 'Browser' ? moment.tz.guess() : kibanaTimezone;
     const fromTime = dateMath.parse(from);
-    const toTime = dateMath.parse(to);
+    const toTime = dateMath.parse(to, { roundUp: true });
 
     if (!fromTime || !toTime) {
       return this.onGenerationFail(
diff --git a/x-pack/plugins/rollup/server/routes/api/index_patterns/register_fields_for_wildcard_route.ts b/x-pack/plugins/rollup/server/routes/api/index_patterns/register_fields_for_wildcard_route.ts
index 250947d72c5fa..df9907fbf731a 100644
--- a/x-pack/plugins/rollup/server/routes/api/index_patterns/register_fields_for_wildcard_route.ts
+++ b/x-pack/plugins/rollup/server/routes/api/index_patterns/register_fields_for_wildcard_route.ts
@@ -8,6 +8,7 @@ import { keyBy } from 'lodash';
 import { schema } from '@kbn/config-schema';
 import { Field } from '../../../lib/merge_capabilities_with_fields';
 import { RouteDependencies } from '../../../types';
+import type { IndexPatternsFetcher as IndexPatternsFetcherType } from '../../../../../../../src/plugins/data/server';
 
 const parseMetaFields = (metaFields: string | string[]) => {
   let parsedFields: string[] = [];
@@ -23,10 +24,10 @@ const getFieldsForWildcardRequest = async (
   context: any,
   request: any,
   response: any,
-  IndexPatternsFetcher: any
+  IndexPatternsFetcher: typeof IndexPatternsFetcherType
 ) => {
-  const { callAsCurrentUser } = context.core.elasticsearch.legacy.client;
-  const indexPatterns = new IndexPatternsFetcher(callAsCurrentUser);
+  const { asCurrentUser } = context.core.elasticsearch.client;
+  const indexPatterns = new IndexPatternsFetcher(asCurrentUser);
   const { pattern, meta_fields: metaFields } = request.query;
 
   let parsedFields: string[] = [];
diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx
index 757e59a4e0583..cf0cb21598c62 100644
--- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx
+++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx
@@ -330,14 +330,16 @@ export class RoleMappingsGridPage extends Component<Props, State> {
               this.state.roles?.find((r) => r.name === rolename) ?? rolename;
 
             return (
-              <RoleTableDisplay
-                role={role}
-                key={rolename}
-                navigateToApp={this.props.navigateToApp}
-              />
+              <EuiFlexItem grow={false} key={rolename}>
+                <RoleTableDisplay role={role} navigateToApp={this.props.navigateToApp} />
+              </EuiFlexItem>
             );
           });
-          return <div data-test-subj="roleMappingRoles">{roleLinks}</div>;
+          return (
+            <EuiFlexGroup gutterSize="s" data-test-subj="roleMappingRoles" wrap>
+              {roleLinks}
+            </EuiFlexGroup>
+          );
         },
       },
       {
diff --git a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx
index 005eebbfbf3bb..eb6d25c9ef5ab 100644
--- a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx
+++ b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx
@@ -66,6 +66,11 @@ describe('<RolesGridPage />', () => {
         kibana: [{ base: [], spaces: [], feature: {} }],
         transient_metadata: { enabled: false },
       },
+      {
+        name: 'special%chars%role',
+        elasticsearch: { cluster: [], indices: [], run_as: [] },
+        kibana: [{ base: [], spaces: [], feature: {} }],
+      },
     ]);
   });
 
@@ -121,7 +126,7 @@ describe('<RolesGridPage />', () => {
     expect(wrapper.find(PermissionDenied)).toMatchSnapshot();
   });
 
-  it('renders role actions as appropriate', async () => {
+  it('renders role actions as appropriate, escaping when necessary', async () => {
     const wrapper = mountWithIntl(
       <RolesGridPage
         rolesAPIClient={apiClientMock}
@@ -137,16 +142,26 @@ describe('<RolesGridPage />', () => {
 
     expect(wrapper.find(PermissionDenied)).toHaveLength(0);
 
-    const editButton = wrapper.find('EuiButtonIcon[data-test-subj="edit-role-action-test-role-1"]');
+    let editButton = wrapper.find('EuiButtonIcon[data-test-subj="edit-role-action-test-role-1"]');
     expect(editButton).toHaveLength(1);
     expect(editButton.prop('href')).toBe('/edit/test-role-1');
 
-    const cloneButton = wrapper.find(
-      'EuiButtonIcon[data-test-subj="clone-role-action-test-role-1"]'
+    editButton = wrapper.find(
+      'EuiButtonIcon[data-test-subj="edit-role-action-special%chars%role"]'
     );
+    expect(editButton).toHaveLength(1);
+    expect(editButton.prop('href')).toBe('/edit/special%25chars%25role');
+
+    let cloneButton = wrapper.find('EuiButtonIcon[data-test-subj="clone-role-action-test-role-1"]');
     expect(cloneButton).toHaveLength(1);
     expect(cloneButton.prop('href')).toBe('/clone/test-role-1');
 
+    cloneButton = wrapper.find(
+      'EuiButtonIcon[data-test-subj="clone-role-action-special%chars%role"]'
+    );
+    expect(cloneButton).toHaveLength(1);
+    expect(cloneButton.prop('href')).toBe('/clone/special%25chars%25role');
+
     expect(
       wrapper.find('EuiButtonIcon[data-test-subj="edit-role-action-disabled-role"]')
     ).toHaveLength(1);
@@ -182,6 +197,11 @@ describe('<RolesGridPage />', () => {
         kibana: [{ base: [], spaces: [], feature: {} }],
         metadata: { _reserved: true },
       },
+      {
+        name: 'special%chars%role',
+        elasticsearch: { cluster: [], indices: [], run_as: [] },
+        kibana: [{ base: [], spaces: [], feature: {} }],
+      },
       {
         name: 'test-role-1',
         elasticsearch: { cluster: [], indices: [], run_as: [] },
@@ -198,6 +218,11 @@ describe('<RolesGridPage />', () => {
         kibana: [{ base: [], spaces: [], feature: {} }],
         transient_metadata: { enabled: false },
       },
+      {
+        name: 'special%chars%role',
+        elasticsearch: { cluster: [], indices: [], run_as: [] },
+        kibana: [{ base: [], spaces: [], feature: {} }],
+      },
       {
         name: 'test-role-1',
         elasticsearch: { cluster: [], indices: [], run_as: [] },
diff --git a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx
index 4c8f45d7eea43..1e733dfa0767e 100644
--- a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx
+++ b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx
@@ -58,7 +58,7 @@ interface State {
 }
 
 const getRoleManagementHref = (action: 'edit' | 'clone', roleName?: string) => {
-  return `/${action}${roleName ? `/${roleName}` : ''}`;
+  return `/${action}${roleName ? `/${encodeURIComponent(roleName)}` : ''}`;
 };
 
 export class RolesGridPage extends Component<Props, State> {
diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx
index df8fe8cee7699..0cc3146172f70 100644
--- a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx
+++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx
@@ -71,6 +71,38 @@ describe('UsersGridPage', () => {
     expect(findTestSubject(wrapper, 'userDisabled')).toHaveLength(0);
   });
 
+  it('generates valid links when usernames contain special characters', async () => {
+    const apiClientMock = userAPIClientMock.create();
+    apiClientMock.getUsers.mockImplementation(() => {
+      return Promise.resolve<User[]>([
+        {
+          username: 'username with some fun characters!@#$%^&*()',
+          email: 'foo@bar.net',
+          full_name: 'foo bar',
+          roles: ['kibana_user'],
+          enabled: true,
+        },
+      ]);
+    });
+
+    const wrapper = mountWithIntl(
+      <UsersGridPage
+        userAPIClient={apiClientMock}
+        rolesAPIClient={rolesAPIClientMock.create()}
+        notifications={coreStart.notifications}
+        history={history}
+        navigateToApp={coreStart.application.navigateToApp}
+      />
+    );
+
+    await waitForRender(wrapper);
+
+    const link = findTestSubject(wrapper, 'userRowUserName');
+    expect(link.props().href).toMatchInlineSnapshot(
+      `"/edit/username%20with%20some%20fun%20characters!%40%23%24%25%5E%26*()"`
+    );
+  });
+
   it('renders a forbidden message if user is not authorized', async () => {
     const apiClient = userAPIClientMock.create();
     apiClient.getUsers.mockRejectedValue({ body: { statusCode: 403 } });
diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx
index 998739a9a83af..debe1c5e82d3b 100644
--- a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx
+++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx
@@ -112,7 +112,7 @@ export class UsersGridPage extends Component<Props, State> {
         render: (username: string) => (
           <EuiLink
             data-test-subj="userRowUserName"
-            {...reactRouterNavigate(this.props.history, `/edit/${username}`)}
+            {...reactRouterNavigate(this.props.history, `/edit/${encodeURIComponent(username)}`)}
           >
             {username}
           </EuiLink>
@@ -151,14 +151,16 @@ export class UsersGridPage extends Component<Props, State> {
           const roleLinks = rolenames.map((rolename, index) => {
             const roleDefinition = roles?.find((role) => role.name === rolename) ?? rolename;
             return (
-              <RoleTableDisplay
-                role={roleDefinition}
-                key={rolename}
-                navigateToApp={this.props.navigateToApp}
-              />
+              <EuiFlexItem grow={false} key={rolename}>
+                <RoleTableDisplay role={roleDefinition} navigateToApp={this.props.navigateToApp} />
+              </EuiFlexItem>
             );
           });
-          return <div data-test-subj="userRowRoles">{roleLinks}</div>;
+          return (
+            <EuiFlexGroup data-test-subj="userRowRoles" gutterSize="s" wrap>
+              {roleLinks}
+            </EuiFlexGroup>
+          );
         },
       },
       {
diff --git a/x-pack/plugins/security_solution/public/common/containers/source/index.tsx b/x-pack/plugins/security_solution/public/common/containers/source/index.tsx
index c36e2de61fcbf..2cc1c75015e07 100644
--- a/x-pack/plugins/security_solution/public/common/containers/source/index.tsx
+++ b/x-pack/plugins/security_solution/public/common/containers/source/index.tsx
@@ -194,15 +194,14 @@ export const useIndexFields = (sourcererScopeName: SourcererScopeName) => {
   const { data, notifications } = useKibana().services;
   const abortCtrl = useRef(new AbortController());
   const dispatch = useDispatch();
-  const previousIndexesName = useRef<string[]>([]);
-
   const indexNamesSelectedSelector = useMemo(
     () => sourcererSelectors.getIndexNamesSelectedSelector(),
     []
   );
-  const indexNames = useShallowEqualSelector<string[]>((state) =>
-    indexNamesSelectedSelector(state, sourcererScopeName)
-  );
+  const { indexNames, previousIndexNames } = useShallowEqualSelector<{
+    indexNames: string[];
+    previousIndexNames: string;
+  }>((state) => indexNamesSelectedSelector(state, sourcererScopeName));
 
   const setLoading = useCallback(
     (loading: boolean) => {
@@ -230,7 +229,6 @@ export const useIndexFields = (sourcererScopeName: SourcererScopeName) => {
               if (!response.isPartial && !response.isRunning) {
                 if (!didCancel) {
                   const stringifyIndices = response.indicesExist.sort().join();
-                  previousIndexesName.current = response.indicesExist;
                   dispatch(
                     sourcererActions.setSource({
                       id: sourcererScopeName,
@@ -279,8 +277,8 @@ export const useIndexFields = (sourcererScopeName: SourcererScopeName) => {
   );
 
   useEffect(() => {
-    if (!isEmpty(indexNames) && !isEqual(previousIndexesName.current, indexNames)) {
+    if (!isEmpty(indexNames) && previousIndexNames !== indexNames.sort().join()) {
       indexFieldsSearch(indexNames);
     }
-  }, [indexNames, indexFieldsSearch, previousIndexesName]);
+  }, [indexNames, indexFieldsSearch, previousIndexNames]);
 };
diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx
index accfb38bc3dc1..22cb4b91fd839 100644
--- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx
@@ -86,7 +86,29 @@ jest.mock('../../utils/apollo_context', () => ({
 }));
 
 describe('Sourcerer Hooks', () => {
-  const state: State = mockGlobalState;
+  const state: State = {
+    ...mockGlobalState,
+    sourcerer: {
+      ...mockGlobalState.sourcerer,
+      sourcererScopes: {
+        ...mockGlobalState.sourcerer.sourcererScopes,
+        [SourcererScopeName.default]: {
+          ...mockGlobalState.sourcerer.sourcererScopes[SourcererScopeName.default],
+          indexPattern: {
+            fields: [],
+            title: '',
+          },
+        },
+        [SourcererScopeName.timeline]: {
+          ...mockGlobalState.sourcerer.sourcererScopes[SourcererScopeName.timeline],
+          indexPattern: {
+            fields: [],
+            title: '',
+          },
+        },
+      },
+    },
+  };
   const { storage } = createSecuritySolutionStorageMock();
   let store = createStore(
     state,
diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.tsx b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.tsx
index b02a09625ccf3..d9f2abeb3832e 100644
--- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.tsx
+++ b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.tsx
@@ -16,6 +16,9 @@ import { ManageScope, SourcererScopeName } from '../../store/sourcerer/model';
 import { useIndexFields } from '../source';
 import { State } from '../../store';
 import { useUserInfo } from '../../../detections/components/user_info';
+import { timelineSelectors } from '../../../timelines/store/timeline';
+import { TimelineId } from '../../../../common/types/timeline';
+import { TimelineModel } from '../../../timelines/store/timeline/model';
 
 export const useInitSourcerer = (
   scopeId: SourcererScopeName.default | SourcererScopeName.detections = SourcererScopeName.default
@@ -29,6 +32,12 @@ export const useInitSourcerer = (
   );
   const ConfigIndexPatterns = useSelector(getConfigIndexPatternsSelector, isEqual);
 
+  const getTimelineSelector = useMemo(() => timelineSelectors.getTimelineByIdSelector(), []);
+  const activeTimeline = useSelector<State, TimelineModel>(
+    (state) => getTimelineSelector(state, TimelineId.active),
+    isEqual
+  );
+
   useIndexFields(scopeId);
   useIndexFields(SourcererScopeName.timeline);
 
@@ -40,7 +49,11 @@ export const useInitSourcerer = (
 
   // Related to timeline
   useEffect(() => {
-    if (!loadingSignalIndex && signalIndexName != null) {
+    if (
+      !loadingSignalIndex &&
+      signalIndexName != null &&
+      (activeTimeline == null || (activeTimeline != null && activeTimeline.savedObjectId == null))
+    ) {
       dispatch(
         sourcererActions.setSelectedIndexPatterns({
           id: SourcererScopeName.timeline,
@@ -48,7 +61,7 @@ export const useInitSourcerer = (
         })
       );
     }
-  }, [ConfigIndexPatterns, dispatch, loadingSignalIndex, signalIndexName]);
+  }, [activeTimeline, ConfigIndexPatterns, dispatch, loadingSignalIndex, signalIndexName]);
 
   // Related to the detection page
   useEffect(() => {
diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/actions.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/actions.ts
index 0b40586798f09..8e92d7559f1d6 100644
--- a/x-pack/plugins/security_solution/public/common/store/sourcerer/actions.ts
+++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/actions.ts
@@ -34,3 +34,9 @@ export const setSelectedIndexPatterns = actionCreator<{
   selectedPatterns: string[];
   eventType?: TimelineEventsType;
 }>('SET_SELECTED_INDEX_PATTERNS');
+
+export const initTimelineIndexPatterns = actionCreator<{
+  id: SourcererScopeName;
+  selectedPatterns: string[];
+  eventType?: TimelineEventsType;
+}>('INIT_TIMELINE_INDEX_PATTERNS');
diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.ts
index 3ae9740cfd51d..42a4fe73c43ba 100644
--- a/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.ts
+++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.ts
@@ -25,16 +25,7 @@ export const createDefaultIndexPatterns = ({ eventType, id, selectedPatterns, st
   if (isEmpty(newSelectedPatterns)) {
     let defaultIndexPatterns = state.configIndexPatterns;
     if (id === SourcererScopeName.timeline && isEmpty(newSelectedPatterns)) {
-      if (eventType === 'all' && !isEmpty(state.signalIndexName)) {
-        defaultIndexPatterns = [...state.configIndexPatterns, state.signalIndexName ?? ''];
-      } else if (eventType === 'raw') {
-        defaultIndexPatterns = state.configIndexPatterns;
-      } else if (
-        !isEmpty(state.signalIndexName) &&
-        (eventType === 'signal' || eventType === 'alert')
-      ) {
-        defaultIndexPatterns = [state.signalIndexName ?? ''];
-      }
+      defaultIndexPatterns = defaultIndexPatternByEventType({ state, eventType });
     } else if (id === SourcererScopeName.detections && isEmpty(newSelectedPatterns)) {
       defaultIndexPatterns = [state.signalIndexName ?? ''];
     }
@@ -42,3 +33,21 @@ export const createDefaultIndexPatterns = ({ eventType, id, selectedPatterns, st
   }
   return newSelectedPatterns;
 };
+
+export const defaultIndexPatternByEventType = ({
+  state,
+  eventType,
+}: {
+  state: SourcererModel;
+  eventType?: TimelineEventsType;
+}) => {
+  let defaultIndexPatterns = state.configIndexPatterns;
+  if (eventType === 'all' && !isEmpty(state.signalIndexName)) {
+    defaultIndexPatterns = [...state.configIndexPatterns, state.signalIndexName ?? ''];
+  } else if (eventType === 'raw') {
+    defaultIndexPatterns = state.configIndexPatterns;
+  } else if (!isEmpty(state.signalIndexName) && (eventType === 'signal' || eventType === 'alert')) {
+    defaultIndexPatterns = [state.signalIndexName ?? ''];
+  }
+  return defaultIndexPatterns;
+};
diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/reducer.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/reducer.ts
index a1112607de24f..0c7c52e5e5733 100644
--- a/x-pack/plugins/security_solution/public/common/store/sourcerer/reducer.ts
+++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/reducer.ts
@@ -4,8 +4,7 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-// Prefer importing entire lodash library, e.g. import { get } from "lodash"
-
+import { isEmpty } from 'lodash/fp';
 import { reducerWithInitialState } from 'typescript-fsa-reducers';
 
 import {
@@ -14,9 +13,10 @@ import {
   setSelectedIndexPatterns,
   setSignalIndexName,
   setSource,
+  initTimelineIndexPatterns,
 } from './actions';
 import { initialSourcererState, SourcererModel } from './model';
-import { createDefaultIndexPatterns } from './helpers';
+import { createDefaultIndexPatterns, defaultIndexPatternByEventType } from './helpers';
 
 export type SourcererState = SourcererModel;
 
@@ -52,6 +52,21 @@ export const sourcererReducer = reducerWithInitialState(initialSourcererState)
       },
     };
   })
+  .case(initTimelineIndexPatterns, (state, { id, selectedPatterns, eventType }) => {
+    return {
+      ...state,
+      sourcererScopes: {
+        ...state.sourcererScopes,
+        [id]: {
+          ...state.sourcererScopes[id],
+          selectedPatterns: isEmpty(selectedPatterns)
+            ? defaultIndexPatternByEventType({ state, eventType })
+            : selectedPatterns,
+        },
+      },
+    };
+  })
+
   .case(setSource, (state, { id, payload }) => {
     const { ...sourcererScopes } = payload;
     return {
diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/selectors.test.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/selectors.test.ts
new file mode 100644
index 0000000000000..e6577f2461a9e
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/selectors.test.ts
@@ -0,0 +1,70 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { cloneDeep } from 'lodash/fp';
+import { mockGlobalState } from '../../mock';
+import { SourcererScopeName } from './model';
+import { getSourcererScopeSelector } from './selectors';
+
+describe('Sourcerer selectors', () => {
+  describe('getSourcererScopeSelector', () => {
+    it('Should exclude elastic cloud alias when selected patterns include "logs-*" as an alias', () => {
+      const mapStateToProps = getSourcererScopeSelector();
+      expect(
+        mapStateToProps(mockGlobalState, SourcererScopeName.default).selectedPatterns
+      ).toEqual([
+        'apm-*-transaction*',
+        'auditbeat-*',
+        'endgame-*',
+        'filebeat-*',
+        'logs-*',
+        'packetbeat-*',
+        'winlogbeat-*',
+        '-*elastic-cloud-logs-*',
+      ]);
+    });
+
+    it('Should NOT exclude elastic cloud alias when selected patterns does NOT include "logs-*" as an alias', () => {
+      const mapStateToProps = getSourcererScopeSelector();
+      const myMockGlobalState = cloneDeep(mockGlobalState);
+      myMockGlobalState.sourcerer.sourcererScopes.default.selectedPatterns = myMockGlobalState.sourcerer.sourcererScopes.default.selectedPatterns.filter(
+        (index) => !index.includes('logs-*')
+      );
+      expect(
+        mapStateToProps(myMockGlobalState, SourcererScopeName.default).selectedPatterns
+      ).toEqual([
+        'apm-*-transaction*',
+        'auditbeat-*',
+        'endgame-*',
+        'filebeat-*',
+        'packetbeat-*',
+        'winlogbeat-*',
+      ]);
+    });
+
+    it('Should NOT exclude elastic cloud alias when selected patterns include "logs-endpoint.event-*" as an alias', () => {
+      const mapStateToProps = getSourcererScopeSelector();
+      const myMockGlobalState = cloneDeep(mockGlobalState);
+      myMockGlobalState.sourcerer.sourcererScopes.default.selectedPatterns = [
+        ...myMockGlobalState.sourcerer.sourcererScopes.default.selectedPatterns.filter(
+          (index) => !index.includes('logs-*')
+        ),
+        'logs-endpoint.event-*',
+      ];
+      expect(
+        mapStateToProps(myMockGlobalState, SourcererScopeName.default).selectedPatterns
+      ).toEqual([
+        'apm-*-transaction*',
+        'auditbeat-*',
+        'endgame-*',
+        'filebeat-*',
+        'packetbeat-*',
+        'winlogbeat-*',
+        'logs-endpoint.event-*',
+      ]);
+    });
+  });
+});
diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/selectors.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/selectors.ts
index ca9ea26ba5bac..e7bd6234cb207 100644
--- a/x-pack/plugins/security_solution/public/common/store/sourcerer/selectors.ts
+++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/selectors.ts
@@ -41,13 +41,18 @@ export const getIndexNamesSelectedSelector = () => {
   const getScopesSelector = scopesSelector();
   const getConfigIndexPatternsSelector = configIndexPatternsSelector();
 
-  const mapStateToProps = (state: State, scopeId: SourcererScopeName): string[] => {
+  const mapStateToProps = (
+    state: State,
+    scopeId: SourcererScopeName
+  ): { indexNames: string[]; previousIndexNames: string } => {
     const scope = getScopesSelector(state)[scopeId];
     const configIndexPatterns = getConfigIndexPatternsSelector(state);
-
-    return scope.selectedPatterns.length === 0 ? configIndexPatterns : scope.selectedPatterns;
+    return {
+      indexNames:
+        scope.selectedPatterns.length === 0 ? configIndexPatterns : scope.selectedPatterns,
+      previousIndexNames: scope.indexPattern.title,
+    };
   };
-
   return mapStateToProps;
 };
 
@@ -81,11 +86,18 @@ export const defaultIndexNamesSelector = () => {
   return mapStateToProps;
 };
 
+const EXLCUDE_ELASTIC_CLOUD_INDEX = '-*elastic-cloud-logs-*';
 export const getSourcererScopeSelector = () => {
   const getScopesSelector = scopesSelector();
 
-  const mapStateToProps = (state: State, scopeId: SourcererScopeName): ManageScope =>
-    getScopesSelector(state)[scopeId];
+  const mapStateToProps = (state: State, scopeId: SourcererScopeName): ManageScope => ({
+    ...getScopesSelector(state)[scopeId],
+    selectedPatterns: getScopesSelector(state)[scopeId].selectedPatterns.some(
+      (index) => index === 'logs-*'
+    )
+      ? [...getScopesSelector(state)[scopeId].selectedPatterns, EXLCUDE_ELASTIC_CLOUD_INDEX]
+      : getScopesSelector(state)[scopeId].selectedPatterns,
+  });
 
   return mapStateToProps;
 };
diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx
index bfc104b105236..ecc0fc54d0d47 100644
--- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx
@@ -47,7 +47,9 @@ describe('alert actions', () => {
     searchStrategyClient = {
       aggs: {} as ISearchStart['aggs'],
       showError: jest.fn(),
-      search: jest.fn().mockResolvedValue({ data: mockTimelineDetails }),
+      search: jest
+        .fn()
+        .mockImplementation(() => ({ toPromise: () => ({ data: mockTimelineDetails }) })),
       searchSource: {} as ISearchStart['searchSource'],
       session: dataPluginMock.createStartContract().search.session,
     };
@@ -400,6 +402,78 @@ describe('alert actions', () => {
         expect(createTimeline).toHaveBeenCalledWith(defaultTimelineProps);
       });
     });
+
+    describe('Eql', () => {
+      test(' with signal.group.id', async () => {
+        const ecsDataMock: Ecs = {
+          ...mockEcsDataWithAlert,
+          signal: {
+            rule: {
+              ...mockEcsDataWithAlert.signal?.rule!,
+              type: ['eql'],
+              timeline_id: [''],
+            },
+            group: {
+              id: ['my-group-id'],
+            },
+          },
+        };
+
+        await sendAlertToTimelineAction({
+          createTimeline,
+          ecsData: ecsDataMock,
+          nonEcsData: [],
+          updateTimelineIsLoading,
+          searchStrategyClient,
+        });
+
+        expect(updateTimelineIsLoading).not.toHaveBeenCalled();
+        expect(createTimeline).toHaveBeenCalledTimes(1);
+        expect(createTimeline).toHaveBeenCalledWith({
+          ...defaultTimelineProps,
+          timeline: {
+            ...defaultTimelineProps.timeline,
+            dataProviders: [
+              {
+                and: [],
+                enabled: true,
+                excluded: false,
+                id:
+                  'send-alert-to-timeline-action-default-draggable-event-details-value-formatted-field-value-timeline-1-alert-id-my-group-id',
+                kqlQuery: '',
+                name: '1',
+                queryMatch: { field: 'signal.group.id', operator: ':', value: 'my-group-id' },
+              },
+            ],
+          },
+        });
+      });
+
+      test(' with NO  signal.group.id', async () => {
+        const ecsDataMock: Ecs = {
+          ...mockEcsDataWithAlert,
+          signal: {
+            rule: {
+              ...mockEcsDataWithAlert.signal?.rule!,
+              type: ['eql'],
+              timeline_id: [''],
+            },
+          },
+        };
+
+        await sendAlertToTimelineAction({
+          createTimeline,
+          ecsData: ecsDataMock,
+          nonEcsData: [],
+          updateTimelineIsLoading,
+          searchStrategyClient,
+        });
+
+        expect(updateTimelineIsLoading).not.toHaveBeenCalled();
+        expect(createTimeline).toHaveBeenCalledTimes(1);
+        expect(createTimeline).toHaveBeenCalledWith(defaultTimelineProps);
+      });
+    });
   });
 
   describe('determineToAndFrom', () => {
diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx
index 043a5afc4480d..e3defaea2ec67 100644
--- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx
@@ -150,8 +150,10 @@ export const getThresholdAggregationDataProvider = (
   ];
 };
 
-export const isEqlRule = (ecsData: Ecs) =>
-  ecsData.signal?.rule?.type?.length && ecsData.signal?.rule?.type[0] === 'eql';
+export const isEqlRuleWithGroupId = (ecsData: Ecs) =>
+  ecsData.signal?.rule?.type?.length &&
+  ecsData.signal?.rule?.type[0] === 'eql' &&
+  ecsData.signal?.group?.id?.length;
 
 export const isThresholdRule = (ecsData: Ecs) =>
   ecsData.signal?.rule?.type?.length && ecsData.signal?.rule?.type[0] === 'threshold';
@@ -181,24 +183,23 @@ export const sendAlertToTimelineAction = async ({
             timelineType: TimelineType.template,
           },
         }),
-        searchStrategyClient.search<
-          TimelineEventsDetailsRequestOptions,
-          TimelineEventsDetailsStrategyResponse
-        >(
-          {
-            defaultIndex: [],
-            docValueFields: [],
-            indexName: ecsData._index ?? '',
-            eventId: ecsData._id,
-            factoryQueryType: TimelineEventsQueries.details,
-          },
-          {
-            strategy: 'securitySolutionTimelineSearchStrategy',
-          }
-        ),
+        searchStrategyClient
+          .search<TimelineEventsDetailsRequestOptions, TimelineEventsDetailsStrategyResponse>(
+            {
+              defaultIndex: [],
+              docValueFields: [],
+              indexName: ecsData._index ?? '',
+              eventId: ecsData._id,
+              factoryQueryType: TimelineEventsQueries.details,
+            },
+            {
+              strategy: 'securitySolutionTimelineSearchStrategy',
+            }
+          )
+          .toPromise(),
       ]);
       const resultingTimeline: TimelineResult = getOr({}, 'data.getOneTimeline', responseTimeline);
-      const eventData: TimelineEventsDetailsItem[] = getOr([], 'data', eventDataResp);
+      const eventData: TimelineEventsDetailsItem[] = eventDataResp.data ?? [];
       if (!isEmpty(resultingTimeline)) {
         const timelineTemplate: TimelineResult = omitTypenameInTimeline(resultingTimeline);
         const { timeline, notes } = formatTimelineResultToModel(
@@ -327,7 +328,7 @@ export const sendAlertToTimelineAction = async ({
         },
       },
     ];
-    if (isEqlRule(ecsData)) {
+    if (isEqlRuleWithGroupId(ecsData)) {
       const signalGroupId = ecsData.signal?.group?.id?.length
         ? ecsData.signal?.group?.id[0]
         : 'unknown-signal-group-id';
diff --git a/x-pack/plugins/security_solution/public/detections/components/user_info/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/user_info/index.test.tsx
index 9b15007136b2e..e87303efbe526 100644
--- a/x-pack/plugins/security_solution/public/detections/components/user_info/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/user_info/index.test.tsx
@@ -42,7 +42,7 @@ describe('useUserInfo', () => {
           isSignalIndexExists: null,
           loading: true,
           signalIndexName: null,
-          signalIndexTemplateOutdated: null,
+          signalIndexMappingOutdated: null,
         },
         error: undefined,
       });
@@ -53,7 +53,7 @@ describe('useUserInfo', () => {
     const spyOnCreateSignalIndex = jest.spyOn(api, 'createSignalIndex');
     const spyOnGetSignalIndex = jest.spyOn(api, 'getSignalIndex').mockResolvedValueOnce({
       name: 'mock-signal-index',
-      template_outdated: true,
+      index_mapping_outdated: true,
     });
     await act(async () => {
       const { waitForNextUpdate } = renderHook(() => useUserInfo(), { wrapper: ManageUserInfo });
diff --git a/x-pack/plugins/security_solution/public/detections/components/user_info/index.tsx b/x-pack/plugins/security_solution/public/detections/components/user_info/index.tsx
index ac2bf438d7fa6..3b0976f459324 100644
--- a/x-pack/plugins/security_solution/public/detections/components/user_info/index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/user_info/index.tsx
@@ -20,7 +20,7 @@ export interface State {
   hasEncryptionKey: boolean | null;
   loading: boolean;
   signalIndexName: string | null;
-  signalIndexTemplateOutdated: boolean | null;
+  signalIndexMappingOutdated: boolean | null;
 }
 
 export const initialState: State = {
@@ -32,7 +32,7 @@ export const initialState: State = {
   hasEncryptionKey: null,
   loading: true,
   signalIndexName: null,
-  signalIndexTemplateOutdated: null,
+  signalIndexMappingOutdated: null,
 };
 
 export type Action =
@@ -66,8 +66,8 @@ export type Action =
       signalIndexName: string | null;
     }
   | {
-      type: 'updateSignalIndexTemplateOutdated';
-      signalIndexTemplateOutdated: boolean | null;
+      type: 'updateSignalIndexMappingOutdated';
+      signalIndexMappingOutdated: boolean | null;
     };
 
 export const userInfoReducer = (state: State, action: Action): State => {
@@ -120,10 +120,10 @@ export const userInfoReducer = (state: State, action: Action): State => {
         signalIndexName: action.signalIndexName,
       };
     }
-    case 'updateSignalIndexTemplateOutdated': {
+    case 'updateSignalIndexMappingOutdated': {
       return {
         ...state,
-        signalIndexTemplateOutdated: action.signalIndexTemplateOutdated,
+        signalIndexMappingOutdated: action.signalIndexMappingOutdated,
       };
     }
     default:
@@ -156,7 +156,7 @@ export const useUserInfo = (): State => {
       hasEncryptionKey,
       loading,
       signalIndexName,
-      signalIndexTemplateOutdated,
+      signalIndexMappingOutdated,
     },
     dispatch,
   ] = useUserData();
@@ -171,7 +171,7 @@ export const useUserInfo = (): State => {
     loading: indexNameLoading,
     signalIndexExists: isApiSignalIndexExists,
     signalIndexName: apiSignalIndexName,
-    signalIndexTemplateOutdated: apiSignalIndexTemplateOutdated,
+    signalIndexMappingOutdated: apiSignalIndexMappingOutdated,
     createDeSignalIndex: createSignalIndex,
   } = useSignalIndex();
 
@@ -234,15 +234,15 @@ export const useUserInfo = (): State => {
   useEffect(() => {
     if (
       !loading &&
-      signalIndexTemplateOutdated !== apiSignalIndexTemplateOutdated &&
-      apiSignalIndexTemplateOutdated != null
+      signalIndexMappingOutdated !== apiSignalIndexMappingOutdated &&
+      apiSignalIndexMappingOutdated != null
     ) {
       dispatch({
-        type: 'updateSignalIndexTemplateOutdated',
-        signalIndexTemplateOutdated: apiSignalIndexTemplateOutdated,
+        type: 'updateSignalIndexMappingOutdated',
+        signalIndexMappingOutdated: apiSignalIndexMappingOutdated,
       });
     }
-  }, [dispatch, loading, signalIndexTemplateOutdated, apiSignalIndexTemplateOutdated]);
+  }, [dispatch, loading, signalIndexMappingOutdated, apiSignalIndexMappingOutdated]);
 
   useEffect(() => {
     if (
@@ -250,7 +250,7 @@ export const useUserInfo = (): State => {
       hasEncryptionKey &&
       hasIndexManage &&
       ((isSignalIndexExists != null && !isSignalIndexExists) ||
-        (signalIndexTemplateOutdated != null && signalIndexTemplateOutdated)) &&
+        (signalIndexMappingOutdated != null && signalIndexMappingOutdated)) &&
       createSignalIndex != null
     ) {
       createSignalIndex();
@@ -261,7 +261,7 @@ export const useUserInfo = (): State => {
     hasEncryptionKey,
     isSignalIndexExists,
     hasIndexManage,
-    signalIndexTemplateOutdated,
+    signalIndexMappingOutdated,
   ]);
 
   return {
@@ -273,6 +273,6 @@ export const useUserInfo = (): State => {
     hasIndexManage,
     hasIndexWrite,
     signalIndexName,
-    signalIndexTemplateOutdated,
+    signalIndexMappingOutdated,
   };
 };
diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/mock.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/mock.ts
index 4fd240348f0f3..21b561ec9cddb 100644
--- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/mock.ts
+++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/mock.ts
@@ -980,7 +980,7 @@ export const mockStatusAlertQuery: object = {
 
 export const mockSignalIndex: AlertsIndex = {
   name: 'mock-signal-index',
-  template_outdated: false,
+  index_mapping_outdated: false,
 };
 
 export const mockUserPrivilege: Privilege = {
diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/types.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/types.ts
index 59ab416ecc824..dadeb1e7958b5 100644
--- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/types.ts
+++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/types.ts
@@ -44,7 +44,7 @@ export interface UpdateAlertStatusProps {
 
 export interface AlertsIndex {
   name: string;
-  template_outdated: boolean;
+  index_mapping_outdated: boolean;
 }
 
 export interface Privilege {
diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx
index 1db952526414a..07375a31f3bbc 100644
--- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx
+++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.test.tsx
@@ -26,7 +26,7 @@ describe('useSignalIndex', () => {
         loading: true,
         signalIndexExists: null,
         signalIndexName: null,
-        signalIndexTemplateOutdated: null,
+        signalIndexMappingOutdated: null,
       });
     });
   });
@@ -43,7 +43,7 @@ describe('useSignalIndex', () => {
         loading: false,
         signalIndexExists: true,
         signalIndexName: 'mock-signal-index',
-        signalIndexTemplateOutdated: false,
+        signalIndexMappingOutdated: false,
       });
     });
   });
@@ -64,7 +64,7 @@ describe('useSignalIndex', () => {
         loading: false,
         signalIndexExists: true,
         signalIndexName: 'mock-signal-index',
-        signalIndexTemplateOutdated: false,
+        signalIndexMappingOutdated: false,
       });
     });
   });
@@ -104,7 +104,7 @@ describe('useSignalIndex', () => {
         loading: false,
         signalIndexExists: false,
         signalIndexName: null,
-        signalIndexTemplateOutdated: null,
+        signalIndexMappingOutdated: null,
       });
     });
   });
@@ -125,7 +125,7 @@ describe('useSignalIndex', () => {
         loading: false,
         signalIndexExists: false,
         signalIndexName: null,
-        signalIndexTemplateOutdated: null,
+        signalIndexMappingOutdated: null,
       });
     });
   });
diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.tsx
index f7d2202736169..1233456359b7f 100644
--- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_signal_index.tsx
@@ -17,7 +17,7 @@ export interface ReturnSignalIndex {
   loading: boolean;
   signalIndexExists: boolean | null;
   signalIndexName: string | null;
-  signalIndexTemplateOutdated: boolean | null;
+  signalIndexMappingOutdated: boolean | null;
   createDeSignalIndex: Func | null;
 }
 
@@ -31,7 +31,7 @@ export const useSignalIndex = (): ReturnSignalIndex => {
   const [signalIndex, setSignalIndex] = useState<Omit<ReturnSignalIndex, 'loading'>>({
     signalIndexExists: null,
     signalIndexName: null,
-    signalIndexTemplateOutdated: null,
+    signalIndexMappingOutdated: null,
     createDeSignalIndex: null,
   });
   const [, dispatchToaster] = useStateToaster();
@@ -49,7 +49,7 @@ export const useSignalIndex = (): ReturnSignalIndex => {
           setSignalIndex({
             signalIndexExists: true,
             signalIndexName: signal.name,
-            signalIndexTemplateOutdated: signal.template_outdated,
+            signalIndexMappingOutdated: signal.index_mapping_outdated,
             createDeSignalIndex: createIndex,
           });
         }
@@ -58,7 +58,7 @@ export const useSignalIndex = (): ReturnSignalIndex => {
           setSignalIndex({
             signalIndexExists: false,
             signalIndexName: null,
-            signalIndexTemplateOutdated: null,
+            signalIndexMappingOutdated: null,
             createDeSignalIndex: createIndex,
           });
           if (isSecurityAppError(error) && error.body.status_code !== 404) {
@@ -89,7 +89,7 @@ export const useSignalIndex = (): ReturnSignalIndex => {
             setSignalIndex({
               signalIndexExists: false,
               signalIndexName: null,
-              signalIndexTemplateOutdated: null,
+              signalIndexMappingOutdated: null,
               createDeSignalIndex: createIndex,
             });
             errorToToaster({ title: i18n.SIGNAL_POST_FAILURE, error, dispatchToaster });
diff --git a/x-pack/plugins/security_solution/public/management/components/management_empty_state.tsx b/x-pack/plugins/security_solution/public/management/components/management_empty_state.tsx
index d51a23639f5cb..18745897c594f 100644
--- a/x-pack/plugins/security_solution/public/management/components/management_empty_state.tsx
+++ b/x-pack/plugins/security_solution/public/management/components/management_empty_state.tsx
@@ -66,7 +66,7 @@ const PolicyEmptyState = React.memo<{
             <EuiText size="s" color="subdued">
               <FormattedMessage
                 id="xpack.securitySolution.endpoint.policyList.onboardingSectionOne"
-                defaultMessage="Endpoint Security protects your hosts with threat prevention, detection, and deep security data visibility."
+                defaultMessage="Protect your hosts with threat prevention, detection, and deep security data visibility."
               />
             </EuiText>
             <EuiSpacer size="m" />
diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/malware.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/malware.tsx
index 1da832fb081ef..6773ed6541927 100644
--- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/malware.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/malware.tsx
@@ -11,6 +11,7 @@ import {
   EuiRadio,
   EuiSwitch,
   EuiTitle,
+  EuiText,
   EuiSpacer,
   htmlIdGenerator,
   EuiCallOut,
@@ -28,6 +29,7 @@ import { policyConfig } from '../../../store/policy_details/selectors';
 import { usePolicyDetailsSelector } from '../../policy_hooks';
 import { clone } from '../../../models/policy_details_config';
 import { LinkToApp } from '../../../../../../common/components/endpoint/link_to_app';
+import { popupVersionsMap } from './popup_options_to_versions';
 
 const ProtectionRadioGroup = styled.div`
   display: flex;
@@ -83,6 +85,25 @@ const ProtectionRadio = React.memo(({ id, label }: { id: ProtectionModes; label:
 
 ProtectionRadio.displayName = 'ProtectionRadio';
 
+const SupportedVersionNotice = ({ optionName }: { optionName: string }) => {
+  const version = popupVersionsMap.get(optionName);
+  if (!version) {
+    return null;
+  }
+
+  return (
+    <EuiText color="subdued" size="xs">
+      <i>
+        <FormattedMessage
+          id="xpack.securitySolution.endpoint.policyDetails.supportedVersion"
+          defaultMessage="Agent version {version}"
+          values={{ version }}
+        />
+      </i>
+    </EuiText>
+  );
+};
+
 /** The Malware Protections form for policy details
  *  which will configure for all relevant OSes.
  */
@@ -189,14 +210,15 @@ export const MalwareProtections = React.memo(() => {
             />
           </h6>
         </EuiTitle>
+        <SupportedVersionNotice optionName="malware" />
+        <EuiSpacer size="s" />
         <EuiCheckbox
           id="xpack.securitySolution.endpoint.policyDetail.malware.userNotification"
           onChange={handleUserNotificationCheckbox}
           checked={userNotificationSelected}
-          label={i18n.translate(
-            'xpack.securitySolution.endpoint.policyDetail.malware.userNotification',
-            { defaultMessage: 'User Notification' }
-          )}
+          label={i18n.translate('xpack.securitySolution.endpoint.policyDetail.malware.notifyUser', {
+            defaultMessage: 'Notify User',
+          })}
         />
       </>
     );
diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/popup_options_to_versions.ts b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/popup_options_to_versions.ts
new file mode 100644
index 0000000000000..d4c7d0102ebd4
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/popup_options_to_versions.ts
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+const popupVersions: Array<[string, string]> = [['malware', '7.11+']];
+
+export const popupVersionsMap: ReadonlyMap<string, string> = new Map<string, string>(popupVersions);
diff --git a/x-pack/plugins/security_solution/public/overview/pages/overview.tsx b/x-pack/plugins/security_solution/public/overview/pages/overview.tsx
index 5a3b4ec384686..a292ec3e1a119 100644
--- a/x-pack/plugins/security_solution/public/overview/pages/overview.tsx
+++ b/x-pack/plugins/security_solution/public/overview/pages/overview.tsx
@@ -131,7 +131,7 @@ const OverviewComponent: React.FC<PropsFromRedux> = ({
                     <EventCounts
                       filters={filters}
                       from={from}
-                      indexNames={[]}
+                      indexNames={selectedPatterns}
                       indexPattern={indexPattern}
                       query={query}
                       setQuery={setQuery}
diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx
index ea8c086c9bdc1..b81bea1d12b27 100644
--- a/x-pack/plugins/security_solution/public/plugin.tsx
+++ b/x-pack/plugins/security_solution/public/plugin.tsx
@@ -414,7 +414,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
         this.subPlugins(),
         startPlugins.data.search
           .search<IndexFieldsStrategyRequest, IndexFieldsStrategyResponse>(
-            { indices: defaultIndicesName, onlyCheckIfIndicesExist: false },
+            { indices: defaultIndicesName, onlyCheckIfIndicesExist: true },
             {
               strategy: 'securitySolutionIndexFields',
             }
diff --git a/x-pack/plugins/security_solution/public/timelines/components/edit_data_provider/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/edit_data_provider/index.tsx
index 2bc202c65f6ab..8127f2be13d4e 100644
--- a/x-pack/plugins/security_solution/public/timelines/components/edit_data_provider/index.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/components/edit_data_provider/index.tsx
@@ -189,7 +189,7 @@ export const StatefulEditDataProvider = React.memo<Props>(
       <EuiPanel paddingSize="s">
         <EuiFlexGroup direction="column" gutterSize="none">
           <EuiFlexItem grow={false}>
-            <EuiFlexGroup direction="row" gutterSize="none" justifyContent="spaceBetween">
+            <EuiFlexGroup gutterSize="s" direction="row" justifyContent="spaceBetween">
               <EuiFlexItem grow={false}>
                 <EuiFormRow label={i18n.FIELD}>
                   <EuiComboBox
@@ -223,7 +223,7 @@ export const StatefulEditDataProvider = React.memo<Props>(
           </EuiFlexItem>
 
           <EuiFlexItem grow={false}>
-            <EuiSpacer />
+            <EuiSpacer size="m" />
           </EuiFlexItem>
 
           {type !== DataProviderType.template &&
@@ -245,7 +245,7 @@ export const StatefulEditDataProvider = React.memo<Props>(
           ) : null}
 
           <EuiFlexItem grow={false}>
-            <EuiSpacer />
+            <EuiSpacer size="m" />
           </EuiFlexItem>
 
           <EuiFlexItem grow={false}>
@@ -265,7 +265,7 @@ export const StatefulEditDataProvider = React.memo<Props>(
                     }) || isValueFieldInvalid
                   }
                   onClick={handleSave}
-                  size="s"
+                  size="m"
                 >
                   {i18n.SAVE}
                 </EuiButton>
diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts
index c89740f667b29..4c3be81a4992a 100644
--- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts
+++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts
@@ -378,7 +378,7 @@ export const dispatchUpdateTimeline = (dispatch: Dispatch): DispatchUpdateTimeli
   ruleNote,
 }: UpdateTimeline): (() => void) => () => {
   dispatch(
-    sourcererActions.setSelectedIndexPatterns({
+    sourcererActions.initTimelineIndexPatterns({
       id: SourcererScopeName.timeline,
       selectedPatterns: timeline.indexNames,
       eventType: timeline.eventType,
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/check_template_version.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/check_template_version.ts
index 473a2dad37f19..e7618f155967b 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/check_template_version.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/check_template_version.ts
@@ -6,20 +6,19 @@
 
 import { get } from 'lodash';
 import { LegacyAPICaller } from '../../../../../../../../src/core/server';
-import { getSignalsTemplate } from './get_signals_template';
 import { getTemplateExists } from '../../index/get_template_exists';
+import { SIGNALS_TEMPLATE_VERSION } from './get_signals_template';
 
 export const templateNeedsUpdate = async (callCluster: LegacyAPICaller, index: string) => {
   const templateExists = await getTemplateExists(callCluster, index);
-  let existingTemplateVersion: number | undefined;
-  if (templateExists) {
-    const existingTemplate: unknown = await callCluster('indices.getTemplate', {
-      name: index,
-    });
-    existingTemplateVersion = get(existingTemplate, [index, 'version']);
+  if (!templateExists) {
+    return true;
   }
-  const newTemplate = getSignalsTemplate(index);
-  if (existingTemplateVersion === undefined || existingTemplateVersion < newTemplate.version) {
+  const existingTemplate: unknown = await callCluster('indices.getTemplate', {
+    name: index,
+  });
+  const existingTemplateVersion: number | undefined = get(existingTemplate, [index, 'version']);
+  if (existingTemplateVersion === undefined || existingTemplateVersion < SIGNALS_TEMPLATE_VERSION) {
     return true;
   }
   return false;
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts
index 070a396d74704..287459cf5ec9a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts
@@ -12,10 +12,11 @@ import { getIndexExists } from '../../index/get_index_exists';
 import { getPolicyExists } from '../../index/get_policy_exists';
 import { setPolicy } from '../../index/set_policy';
 import { setTemplate } from '../../index/set_template';
-import { getSignalsTemplate } from './get_signals_template';
+import { getSignalsTemplate, SIGNALS_TEMPLATE_VERSION } from './get_signals_template';
 import { createBootstrapIndex } from '../../index/create_bootstrap_index';
 import signalsPolicy from './signals_policy.json';
 import { templateNeedsUpdate } from './check_template_version';
+import { getIndexVersion } from './get_index_version';
 
 export const createIndexRoute = (router: IRouter) => {
   router.post(
@@ -67,18 +68,20 @@ export const createDetectionIndex = async (
   }
 
   const index = siemClient.getSignalsIndex();
-  const indexExists = await getIndexExists(callCluster, index);
+  const policyExists = await getPolicyExists(callCluster, index);
+  if (!policyExists) {
+    await setPolicy(callCluster, index, signalsPolicy);
+  }
   if (await templateNeedsUpdate(callCluster, index)) {
-    const policyExists = await getPolicyExists(callCluster, index);
-    if (!policyExists) {
-      await setPolicy(callCluster, index, signalsPolicy);
-    }
     await setTemplate(callCluster, index, getSignalsTemplate(index));
-    if (indexExists) {
+  }
+  const indexExists = await getIndexExists(callCluster, index);
+  if (indexExists) {
+    const indexVersion = await getIndexVersion(callCluster, index);
+    if (indexVersion !== SIGNALS_TEMPLATE_VERSION) {
       await callCluster('indices.rollover', { alias: index });
     }
-  }
-  if (!indexExists) {
+  } else {
     await createBootstrapIndex(callCluster, index);
   }
 };
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_index_version.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_index_version.ts
new file mode 100644
index 0000000000000..062cffd393555
--- /dev/null
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_index_version.ts
@@ -0,0 +1,36 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { get } from 'lodash';
+import { LegacyAPICaller } from '../../../../../../../../src/core/server';
+import { readIndex } from '../../index/read_index';
+
+interface IndicesAliasResponse {
+  [index: string]: IndexAliasResponse;
+}
+
+interface IndexAliasResponse {
+  aliases: {
+    [aliasName: string]: Record<string, unknown>;
+  };
+}
+
+export const getIndexVersion = async (
+  callCluster: LegacyAPICaller,
+  index: string
+): Promise<number | undefined> => {
+  const indexAlias: IndicesAliasResponse = await callCluster('indices.getAlias', {
+    index,
+  });
+  const writeIndex = Object.keys(indexAlias).find(
+    (key) => indexAlias[key].aliases[index].is_write_index
+  );
+  if (writeIndex === undefined) {
+    return undefined;
+  }
+  const writeIndexMapping = await readIndex(callCluster, writeIndex);
+  return get(writeIndexMapping, [writeIndex, 'mappings', '_meta', 'version']);
+};
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_signals_template.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_signals_template.ts
index b676ab5705bfc..d1a9b701b2c9d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_signals_template.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/get_signals_template.ts
@@ -7,8 +7,10 @@
 import signalsMapping from './signals_mapping.json';
 import ecsMapping from './ecs_mapping.json';
 
+export const SIGNALS_TEMPLATE_VERSION = 2;
+export const MIN_EQL_RULE_INDEX_VERSION = 2;
+
 export const getSignalsTemplate = (index: string) => {
-  const version = 2;
   const template = {
     settings: {
       index: {
@@ -31,10 +33,10 @@ export const getSignalsTemplate = (index: string) => {
         signal: signalsMapping.mappings.properties.signal,
       },
       _meta: {
-        version,
+        version: SIGNALS_TEMPLATE_VERSION,
       },
     },
-    version,
+    version: SIGNALS_TEMPLATE_VERSION,
   };
   return template;
 };
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/read_index_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/read_index_route.ts
index b9ae8b546b8bd..d1b1a2b4dd0eb 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/read_index_route.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/read_index_route.ts
@@ -8,7 +8,8 @@ import { IRouter } from '../../../../../../../../src/core/server';
 import { DETECTION_ENGINE_INDEX_URL } from '../../../../../common/constants';
 import { transformError, buildSiemResponse } from '../utils';
 import { getIndexExists } from '../../index/get_index_exists';
-import { templateNeedsUpdate } from './check_template_version';
+import { SIGNALS_TEMPLATE_VERSION } from './get_signals_template';
+import { getIndexVersion } from './get_index_version';
 
 export const readIndexRoute = (router: IRouter) => {
   router.get(
@@ -32,10 +33,24 @@ export const readIndexRoute = (router: IRouter) => {
 
         const index = siemClient.getSignalsIndex();
         const indexExists = await getIndexExists(clusterClient.callAsCurrentUser, index);
-        const templateOutdated = await templateNeedsUpdate(clusterClient.callAsCurrentUser, index);
 
         if (indexExists) {
-          return response.ok({ body: { name: index, template_outdated: templateOutdated } });
+          let mappingOutdated: boolean | null = null;
+          try {
+            const indexVersion = await getIndexVersion(clusterClient.callAsCurrentUser, index);
+            mappingOutdated = indexVersion !== SIGNALS_TEMPLATE_VERSION;
+          } catch (err) {
+            const error = transformError(err);
+            // Some users may not have the view_index_metadata permission necessary to check the index mapping version
+            // so just continue and return null for index_mapping_outdated if the error is a 403
+            if (error.statusCode !== 403) {
+              return siemResponse.error({
+                body: error.message,
+                statusCode: error.statusCode,
+              });
+            }
+          }
+          return response.ok({ body: { name: index, index_mapping_outdated: mappingOutdated } });
         } else {
           return siemResponse.error({
             statusCode: 404,
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts
index 6768e9534a87e..977dad680f8a4 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts
@@ -7,7 +7,9 @@
 import Boom from 'boom';
 
 import { SavedObjectsFindResponse } from 'kibana/server';
-import { IRuleSavedAttributesSavedObjectAttributes, IRuleStatusAttributes } from '../rules/types';
+
+import { alertsClientMock } from '../../../../../alerts/server/mocks';
+import { IRuleSavedAttributesSavedObjectAttributes, IRuleStatusSOAttributes } from '../rules/types';
 import { BadRequestError } from '../errors/bad_request_error';
 import {
   transformError,
@@ -19,8 +21,14 @@ import {
   transformImportError,
   convertToSnakeCase,
   SiemResponseFactory,
+  mergeStatuses,
+  getFailingRules,
 } from './utils';
 import { responseMock } from './__mocks__';
+import { exampleRuleStatus, exampleFindRuleStatusResponse } from '../signals/__mocks__/es_results';
+import { getResult } from './__mocks__/request_responses';
+
+let alertsClient: ReturnType<typeof alertsClientMock.create>;
 
 describe('utils', () => {
   describe('transformError', () => {
@@ -319,7 +327,7 @@ describe('utils', () => {
         saved_objects: [],
       };
       expect(
-        convertToSnakeCase<IRuleStatusAttributes>(values.saved_objects[0]?.attributes) // this is undefined, but it says it's not
+        convertToSnakeCase<IRuleStatusSOAttributes>(values.saved_objects[0]?.attributes) // this is undefined, but it says it's not
       ).toEqual(null);
     });
   });
@@ -350,4 +358,133 @@ describe('utils', () => {
       );
     });
   });
+
+  describe('mergeStatuses', () => {
+    it('merges statuses and converts from camelCase saved object to snake_case HTTP response', () => {
+      const statusOne = exampleRuleStatus();
+      statusOne.attributes.status = 'failed';
+      const statusTwo = exampleRuleStatus();
+      statusTwo.attributes.status = 'failed';
+      const currentStatus = exampleRuleStatus();
+      const foundRules = exampleFindRuleStatusResponse([currentStatus, statusOne, statusTwo]);
+      const res = mergeStatuses(currentStatus.attributes.alertId, foundRules.saved_objects, {
+        'myfakealertid-8cfac': {
+          current_status: {
+            alert_id: 'myfakealertid-8cfac',
+            status_date: '2020-03-27T22:55:59.517Z',
+            status: 'succeeded',
+            last_failure_at: null,
+            last_success_at: '2020-03-27T22:55:59.517Z',
+            last_failure_message: null,
+            last_success_message: 'succeeded',
+            gap: null,
+            bulk_create_time_durations: [],
+            search_after_time_durations: [],
+            last_look_back_date: null,
+          },
+          failures: [],
+        },
+      });
+      expect(res).toEqual({
+        'myfakealertid-8cfac': {
+          current_status: {
+            alert_id: 'myfakealertid-8cfac',
+            status_date: '2020-03-27T22:55:59.517Z',
+            status: 'succeeded',
+            last_failure_at: null,
+            last_success_at: '2020-03-27T22:55:59.517Z',
+            last_failure_message: null,
+            last_success_message: 'succeeded',
+            gap: null,
+            bulk_create_time_durations: [],
+            search_after_time_durations: [],
+            last_look_back_date: null,
+          },
+          failures: [],
+        },
+        'f4b8e31d-cf93-4bde-a265-298bde885cd7': {
+          current_status: {
+            alert_id: 'f4b8e31d-cf93-4bde-a265-298bde885cd7',
+            status_date: '2020-03-27T22:55:59.517Z',
+            status: 'succeeded',
+            last_failure_at: null,
+            last_success_at: '2020-03-27T22:55:59.517Z',
+            last_failure_message: null,
+            last_success_message: 'succeeded',
+            gap: null,
+            bulk_create_time_durations: [],
+            search_after_time_durations: [],
+            last_look_back_date: null,
+          },
+          failures: [
+            {
+              alert_id: 'f4b8e31d-cf93-4bde-a265-298bde885cd7',
+              status_date: '2020-03-27T22:55:59.517Z',
+              status: 'failed',
+              last_failure_at: null,
+              last_success_at: '2020-03-27T22:55:59.517Z',
+              last_failure_message: null,
+              last_success_message: 'succeeded',
+              gap: null,
+              bulk_create_time_durations: [],
+              search_after_time_durations: [],
+              last_look_back_date: null,
+            },
+            {
+              alert_id: 'f4b8e31d-cf93-4bde-a265-298bde885cd7',
+              status_date: '2020-03-27T22:55:59.517Z',
+              status: 'failed',
+              last_failure_at: null,
+              last_success_at: '2020-03-27T22:55:59.517Z',
+              last_failure_message: null,
+              last_success_message: 'succeeded',
+              gap: null,
+              bulk_create_time_durations: [],
+              search_after_time_durations: [],
+              last_look_back_date: null,
+            },
+          ],
+        },
+      });
+    });
+  });
+
+  describe('getFailingRules', () => {
+    beforeEach(() => {
+      alertsClient = alertsClientMock.create();
+    });
+    it('getFailingRules finds no failing rules', async () => {
+      alertsClient.get.mockResolvedValue(getResult());
+      const res = await getFailingRules(['my-fake-id'], alertsClient);
+      expect(res).toEqual({});
+    });
+    it('getFailingRules finds a failing rule', async () => {
+      const foundRule = getResult();
+      foundRule.executionStatus = {
+        status: 'error',
+        lastExecutionDate: foundRule.executionStatus.lastExecutionDate,
+        error: {
+          reason: 'read',
+          message: 'oops',
+        },
+      };
+      alertsClient.get.mockResolvedValue(foundRule);
+      const res = await getFailingRules([foundRule.id], alertsClient);
+      expect(res).toEqual({ [foundRule.id]: foundRule });
+    });
+    it('getFailingRules throws an error', async () => {
+      alertsClient.get.mockImplementation(() => {
+        throw new Error('my test error');
+      });
+      let error;
+      try {
+        await getFailingRules(['my-fake-id'], alertsClient);
+      } catch (exc) {
+        error = exc;
+      }
+      expect(error.message).toEqual(
+        'Failed to get executionStatus with AlertsClient: my test error'
+      );
+    });
+  });
 });
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts
index 96f96d7ebcc9e..72be7a3c0fa08 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts
@@ -17,7 +17,7 @@ import {
 } from '../../../../../../../src/core/server';
 import { AlertsClient } from '../../../../../alerts/server';
 import { BadRequestError } from '../errors/bad_request_error';
-import { RuleStatusResponse, IRuleStatusAttributes } from '../rules/types';
+import { RuleStatusResponse, IRuleStatusSOAttributes } from '../rules/types';
 
 export interface OutputError {
   message: string;
@@ -294,39 +294,53 @@ export const convertToSnakeCase = <T extends Record<string, unknown>>(
   }, {});
 };
 
+/**
+ *
+ * @param id rule id
+ * @param currentStatusAndFailures array of rule statuses where the 0th status is the current status and 1-5 positions are the historical failures
+ * @param acc accumulated rule id : statuses
+ */
 export const mergeStatuses = (
   id: string,
-  failures: Array<SavedObjectsFindResult<IRuleStatusAttributes>>,
+  currentStatusAndFailures: Array<SavedObjectsFindResult<IRuleStatusSOAttributes>>,
   acc: RuleStatusResponse
-) => {
-  if (failures.length === 0) {
+): RuleStatusResponse => {
+  if (currentStatusAndFailures.length === 0) {
     return {
       ...acc,
     };
   }
-  const convertedCurrentStatus = convertToSnakeCase<IRuleStatusAttributes>(failures[0].attributes);
+  const convertedCurrentStatus = convertToSnakeCase<IRuleStatusSOAttributes>(
+    currentStatusAndFailures[0].attributes
+  );
   return {
     ...acc,
     [id]: {
       current_status: convertedCurrentStatus,
-      failures: failures.map((errorItem) =>
-        convertToSnakeCase<IRuleStatusAttributes>(errorItem.attributes)
-      ),
+      failures: currentStatusAndFailures
+        .slice(1)
+        .map((errorItem) => convertToSnakeCase<IRuleStatusSOAttributes>(errorItem.attributes)),
     },
   } as RuleStatusResponse;
 };
 
-export const getFailingRules = (ids: string[], alertsClient: AlertsClient) =>
-  Promise.all(
-    ids.map(async (id) =>
-      alertsClient.get({
-        id,
-      })
-    )
-  )
-    .then((rules) => rules.filter((rule) => rule.executionStatus.status === 'error'))
-    .then((rules) =>
-      rules.reduce((acc, failingRule) => {
+export type GetFailingRulesResult = Record<string, SanitizedAlert>;
+
+export const getFailingRules = async (
+  ids: string[],
+  alertsClient: AlertsClient
+): Promise<GetFailingRulesResult> => {
+  try {
+    const errorRules = await Promise.all(
+      ids.map(async (id) =>
+        alertsClient.get({
+          id,
+        })
+      )
+    );
+    return errorRules
+      .filter((rule) => rule.executionStatus.status === 'error')
+      .reduce<GetFailingRulesResult>((acc, failingRule) => {
         const accum = acc;
         const theRule = failingRule;
         return {
@@ -335,5 +349,8 @@ export const getFailingRules = (ids: string[], alertsClient: AlertsClient) =>
           },
           ...accum,
         };
-      }, {} as Record<string, SanitizedAlert>)
-    );
+      }, {});
+  } catch (exc) {
+    throw new Error(`Failed to get executionStatus with AlertsClient: ${exc.message}`);
+  }
+};
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_403_response_to_a_post.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_403_response_to_a_post.json
index 9139ca82cc7d8..44deb00140654 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_403_response_to_a_post.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_403_response_to_a_post.json
@@ -20,9 +20,9 @@
   "rule_id": "a87a4e42-1d82-44bd-b0bf-d9b7f91fb89e",
   "severity": "medium",
   "tags": [
-    "APM",
-    "Elastic"
+    "Elastic",
+    "APM"
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_405_response_method_not_allowed.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_405_response_method_not_allowed.json
index 2eb7d711e5fb8..5ff5cb39a6b21 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_405_response_method_not_allowed.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_405_response_method_not_allowed.json
@@ -20,9 +20,9 @@
   "rule_id": "75ee75d8-c180-481c-ba88-ee50129a6aef",
   "severity": "medium",
   "tags": [
-    "APM",
-    "Elastic"
+    "Elastic",
+    "APM"
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_null_user_agent.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_null_user_agent.json
index e78395be8fb1b..75bbfe477732b 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_null_user_agent.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_null_user_agent.json
@@ -38,9 +38,9 @@
   "rule_id": "43303fd4-4839-4e48-b2b2-803ab060758d",
   "severity": "medium",
   "tags": [
-    "APM",
-    "Elastic"
+    "Elastic",
+    "APM"
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_sqlmap_user_agent.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_sqlmap_user_agent.json
index aaaab6b5c6031..10185c28a8e52 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_sqlmap_user_agent.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_sqlmap_user_agent.json
@@ -20,9 +20,9 @@
   "rule_id": "d49cc73f-7a16-4def-89ce-9fc7127d7820",
   "severity": "medium",
   "tags": [
-    "APM",
-    "Elastic"
+    "Elastic",
+    "APM"
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_network_connection_from_windows_binary.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_network_connection_from_windows_binary.json
deleted file mode 100644
index 5652f025952d7..0000000000000
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_network_connection_from_windows_binary.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
-  "author": [
-    "Elastic"
-  ],
-  "description": "Identifies network activity from unexpected system applications. This may indicate adversarial activity as these applications are often leveraged by adversaries to execute code and evade detection.",
-  "from": "now-9m",
-  "index": [
-    "logs-endpoint.events.*",
-    "winlogbeat-*"
-  ],
-  "language": "eql",
-  "license": "Elastic License",
-  "name": "Unusual Network Activity from a Windows System Binary",
-  "query": "sequence by process.entity_id with maxspan=5m\n  [process where event.type in (\"start\", \"process_started\") and\n\n     /* known applocker bypasses */\n     process.name in (\"bginfo.exe\",\n                      \"cdb.exe\",\n                      \"control.exe\",\n                      \"cmstp.exe\",\n                      \"csi.exe\",\n                      \"dnx.exe\",\n                      \"fsi.exe\",\n                      \"ieexec.exe\",\n                      \"iexpress.exe\",\n                      \"installutil.exe\",\n                      \"Microsoft.Workflow.Compiler.exe\",\n                      \"MSBuild.exe\",\n                      \"msdt.exe\",\n                      \"mshta.exe\",\n                      \"msiexec.exe\",\n                      \"msxsl.exe\",\n                      \"odbcconf.exe\",\n                      \"rcsi.exe\",\n                      \"regsvr32.exe\",\n                      \"xwizard.exe\")]\n  [network where event.type == \"connection\" and\n     process.name in (\"bginfo.exe\",\n                      \"cdb.exe\",\n                      \"control.exe\",\n                      \"cmstp.exe\",\n                      \"csi.exe\",\n                      \"dnx.exe\",\n                      \"fsi.exe\",\n                      \"ieexec.exe\",\n                      \"iexpress.exe\",\n                      \"installutil.exe\",\n                      \"Microsoft.Workflow.Compiler.exe\",\n                      \"MSBuild.exe\",\n                      \"msdt.exe\",\n                      \"mshta.exe\",\n                      \"msiexec.exe\",\n                      \"msxsl.exe\",\n                      \"odbcconf.exe\",\n                      \"rcsi.exe\",\n                      \"regsvr32.exe\",\n                      \"xwizard.exe\")]\n",
-  "risk_score": 21,
-  "rule_id": "1fe3b299-fbb5-4657-a937-1d746f2c711a",
-  "severity": "medium",
-  "tags": [
-    "Elastic",
-    "Windows"
-  ],
-  "threat": [
-    {
-      "framework": "MITRE ATT&CK",
-      "tactic": {
-        "id": "TA0005",
-        "name": "Defense Evasion",
-        "reference": "https://attack.mitre.org/tactics/TA0005/"
-      },
-      "technique": [
-        {
-          "id": "T1127",
-          "name": "Trusted Developer Utilities Proxy Execution",
-          "reference": "https://attack.mitre.org/techniques/T1127/"
-        }
-      ]
-    }
-  ],
-  "type": "eql",
-  "version": 1
-}
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_cloudtrail_logging_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_cloudtrail_logging_created.json
index 3dc084a3af54b..7c98f47fd05e2 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_cloudtrail_logging_created.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_cloudtrail_logging_created.json
@@ -25,11 +25,12 @@
   "rule_id": "594e0cbf-86cc-45aa-9ff7-ff27db27d3ed",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Logging",
-    "Continuous Monitoring"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_subscription_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_subscription_creation.json
index 720c6f71dafdd..6b90ec776926c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_subscription_creation.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_subscription_creation.json
@@ -22,10 +22,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
-    "Logging"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_topic_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_topic_creation.json
index 93695334faae2..e53c36b236639 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_topic_creation.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_topic_creation.json
@@ -22,10 +22,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
-    "Logging"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_update_event_hub_auth_rule.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_update_event_hub_auth_rule.json
index cddc98ba2e6d7..d65a0bcdbc6d0 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_update_event_hub_auth_rule.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_update_event_hub_auth_rule.json
@@ -22,11 +22,12 @@
   "rule_id": "b6dce542-2b75-4ffb-b7d6-38787298ba9d",
   "severity": "medium",
   "tags": [
-    "Azure",
     "Elastic",
-    "SecOps",
+    "Cloud",
+    "Azure",
     "Continuous Monitoring",
-    "Logging"
+    "SecOps",
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_certutil_network_connection.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_certutil_network_connection.json
index f32877da78d99..e88297aa2c813 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_certutil_network_connection.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_certutil_network_connection.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_cobalt_strike_beacon.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_cobalt_strike_beacon.json
index 7ebc13ac8079b..27ad410df1fa2 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_cobalt_strike_beacon.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_cobalt_strike_beacon.json
@@ -23,7 +23,9 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Network"
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_dns_directly_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_dns_directly_to_the_internet.json
index 79ec202c41ffb..3df567b09055a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_dns_directly_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_dns_directly_to_the_internet.json
@@ -23,7 +23,9 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Network"
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
@@ -43,5 +45,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_download_rar_powershell_from_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_download_rar_powershell_from_internet.json
index 7b739f005a0cb..92411011ba66e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_download_rar_powershell_from_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_download_rar_powershell_from_internet.json
@@ -23,7 +23,9 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Network"
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_fin7_c2_behavior.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_fin7_c2_behavior.json
index 04d68aff0da1c..1ea40aad7861a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_fin7_c2_behavior.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_fin7_c2_behavior.json
@@ -22,7 +22,9 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Network"
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_ftp_file_transfer_protocol_activity_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_ftp_file_transfer_protocol_activity_to_the_internet.json
index 9a009ffd3fd21..c73fdf1bded9d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_ftp_file_transfer_protocol_activity_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_ftp_file_transfer_protocol_activity_to_the_internet.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
@@ -54,5 +58,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_halfbaked_beacon.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_halfbaked_beacon.json
index 7dacb9afcbd60..19c2832b4b82e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_halfbaked_beacon.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_halfbaked_beacon.json
@@ -23,7 +23,9 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Network"
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_irc_internet_relay_chat_protocol_activity_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_irc_internet_relay_chat_protocol_activity_to_the_internet.json
index 0e35d4b1c5ca0..f1901fa70def2 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_irc_internet_relay_chat_protocol_activity_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_irc_internet_relay_chat_protocol_activity_to_the_internet.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_nat_traversal_port_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_nat_traversal_port_activity.json
index e42bf4029eb01..5afdd1f629ae4 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_nat_traversal_port_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_nat_traversal_port_activity.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
@@ -39,5 +43,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_26_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_26_activity.json
index 1cdfd44eb2adf..edd913da4d2b3 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_26_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_26_activity.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -23,7 +24,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_8000_activity_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_8000_activity_to_the_internet.json
index 319f95ed88e08..0c35bd5e23ed5 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_8000_activity_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_8000_activity_to_the_internet.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
@@ -39,5 +43,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_pptp_point_to_point_tunneling_protocol_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_pptp_point_to_point_tunneling_protocol_activity.json
index bd478f2b23fc0..c706a5b7248c8 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_pptp_point_to_point_tunneling_protocol_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_pptp_point_to_point_tunneling_protocol_activity.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
@@ -39,5 +43,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_proxy_port_activity_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_proxy_port_activity_to_the_internet.json
index ee02505300611..8535a9591b88f 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_proxy_port_activity_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_proxy_port_activity_to_the_internet.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
@@ -39,5 +43,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_rdp_remote_desktop_protocol_from_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_rdp_remote_desktop_protocol_from_the_internet.json
index 87544647b17e1..4a3fd026f54a7 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_rdp_remote_desktop_protocol_from_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_rdp_remote_desktop_protocol_from_the_internet.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
@@ -69,5 +73,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_remote_file_copy_desktopimgdownldr.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_remote_file_copy_desktopimgdownldr.json
index d5b21dfe2db18..596c4bbac57ba 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_remote_file_copy_desktopimgdownldr.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_remote_file_copy_desktopimgdownldr.json
@@ -11,7 +11,7 @@
   "language": "kuery",
   "license": "Elastic License",
   "name": "Remote File Download via Desktopimgdownldr Utility",
-  "query": "event.category:process and event.type:(start or process_started) and (process.name:desktopimgdownldr.exe or process.pe.original_file_name:desktopimgdownldr.exe) and process.args:/lockscreenurl\\:http*",
+  "query": "event.category:process and event.type:(start or process_started) and (process.name:desktopimgdownldr.exe or process.pe.original_file_name:desktopimgdownldr.exe or winlog.event_data.OriginalFileName:desktopimgdownldr.exe) and process.args:/lockscreenurl\\:http*",
   "references": [
     "https://labs.sentinelone.com/living-off-windows-land-a-new-native-file-downldr/"
   ],
@@ -20,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_remote_file_copy_mpcmdrun.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_remote_file_copy_mpcmdrun.json
index aeadc849eac17..9eef2fbbc62a6 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_remote_file_copy_mpcmdrun.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_remote_file_copy_mpcmdrun.json
@@ -12,7 +12,7 @@
   "license": "Elastic License",
   "name": "Remote File Download via MpCmdRun",
   "note": "### Investigating Remote File Download via MpCmdRun\nVerify details such as the parent process, URL reputation, and downloaded file details. Additionally, `MpCmdRun` logs this information in the Appdata Temp folder in `MpCmdRun.log`.",
-  "query": "event.category:process and event.type:(start or process_started) and (process.name:MpCmdRun.exe or process.pe.original_file_name:MpCmdRun.exe) and process.args:((\"-DownloadFile\" or \"-downloadfile\") and \"-url\" and \"-path\")",
+  "query": "event.category:process and event.type:(start or process_started) and (process.name:MpCmdRun.exe or process.pe.original_file_name:MpCmdRun.exe or winlog.event_data.OriginalFileName:MpCmdRun.exe) and process.args:((\"-DownloadFile\" or \"-downloadfile\") and \"-url\" and \"-path\")",
   "references": [
     "https://twitter.com/mohammadaskar2/status/1301263551638761477",
     "https://www.bleepingcomputer.com/news/microsoft/microsoft-defender-can-ironically-be-used-to-download-malware/"
@@ -22,7 +22,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_smtp_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_smtp_to_the_internet.json
index 3a082c29a4cf1..f041255374f12 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_smtp_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_smtp_to_the_internet.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
@@ -54,5 +58,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_sql_server_port_activity_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_sql_server_port_activity_to_the_internet.json
index 95ac4d8836800..7e4f3907fc31e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_sql_server_port_activity_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_sql_server_port_activity_to_the_internet.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
@@ -39,5 +43,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_ssh_secure_shell_from_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_ssh_secure_shell_from_the_internet.json
index fe5608459ffce..08ab14aeb5c7c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_ssh_secure_shell_from_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_ssh_secure_shell_from_the_internet.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
@@ -69,5 +73,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_ssh_secure_shell_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_ssh_secure_shell_to_the_internet.json
index 9ecfe39a79303..4bc48ebe0c316 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_ssh_secure_shell_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_ssh_secure_shell_to_the_internet.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
@@ -39,5 +43,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_teamviewer_remote_file_copy.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_teamviewer_remote_file_copy.json
index 793ff4ebda72f..c597f6b2718b9 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_teamviewer_remote_file_copy.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_teamviewer_remote_file_copy.json
@@ -20,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_telnet_port_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_telnet_port_activity.json
index 4455d8adfdf83..9007db322ae58 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_telnet_port_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_telnet_port_activity.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_tor_activity_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_tor_activity_to_the_internet.json
index b278c36d01c1b..e82106a87bc2e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_tor_activity_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_tor_activity_to_the_internet.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
@@ -54,5 +58,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_from_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_from_the_internet.json
index 97d2b940a6949..9321d2a2103de 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_from_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_from_the_internet.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_to_the_internet.json
index 97757af22be0c..38f38e9762645 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_to_the_internet.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Command and Control"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempted_bypass_of_okta_mfa.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempted_bypass_of_okta_mfa.json
index 118f8f6b2ad4a..fb8256bf2509c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempted_bypass_of_okta_mfa.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempted_bypass_of_okta_mfa.json
@@ -21,10 +21,11 @@
   "severity": "high",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Identity and Access",
-    "Continuous Monitoring"
+    "Identity and Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempts_to_brute_force_okta_user_account.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempts_to_brute_force_okta_user_account.json
index 5aae95476e9da..d8d5b5305aaaa 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempts_to_brute_force_okta_user_account.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempts_to_brute_force_okta_user_account.json
@@ -22,6 +22,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_aws_iam_assume_role_brute_force.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_aws_iam_assume_role_brute_force.json
index e350c3697f685..b7e89a9120bbb 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_aws_iam_assume_role_brute_force.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_aws_iam_assume_role_brute_force.json
@@ -21,11 +21,12 @@
   "rule_id": "ea248a02-bc47-4043-8e94-2885b19b2636",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Identity and Access",
-    "Continuous Monitoring"
+    "Identity and Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_compress_credentials_keychains.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_compress_credentials_keychains.json
similarity index 95%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_compress_credentials_keychains.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_compress_credentials_keychains.json
index bf2a52066ae1c..c13ac69e50987 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_compress_credentials_keychains.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_compress_credentials_keychains.json
@@ -20,7 +20,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "MacOS"
+    "Host",
+    "macOS",
+    "Threat Detection",
+    "Credential Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_credential_dumping_msbuild.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_credential_dumping_msbuild.json
index a67fa01ab371a..0761ba515d9b1 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_credential_dumping_msbuild.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_credential_dumping_msbuild.json
@@ -20,7 +20,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Credential Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_domain_backup_dpapi_private_keys.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_domain_backup_dpapi_private_keys.json
index dc4f5e11754d3..eefd6ee9e601b 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_domain_backup_dpapi_private_keys.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_domain_backup_dpapi_private_keys.json
@@ -22,7 +22,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Credential Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_gcp_iam_service_account_key_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_gcp_iam_service_account_key_deletion.json
index 63d5081869f1b..5db891caa2857 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_gcp_iam_service_account_key_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_gcp_iam_service_account_key_deletion.json
@@ -23,6 +23,7 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_gcp_key_created_for_service_account.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_gcp_key_created_for_service_account.json
index c1ae7f5fc1953..a6d45b7465771 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_gcp_key_created_for_service_account.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_gcp_key_created_for_service_account.json
@@ -23,6 +23,7 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iam_user_addition_to_group.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iam_user_addition_to_group.json
index 7c5aa9bc7f3a8..8244cb755787f 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iam_user_addition_to_group.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iam_user_addition_to_group.json
@@ -24,11 +24,12 @@
   "rule_id": "333de828-8190-4cf5-8d7c-7575846f6fe0",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Identity and Access",
-    "Continuous Monitoring"
+    "Identity and Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iis_apppoolsa_pwd_appcmd.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iis_apppoolsa_pwd_appcmd.json
index dd7bc43c58382..6a182617945f1 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iis_apppoolsa_pwd_appcmd.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iis_apppoolsa_pwd_appcmd.json
@@ -12,7 +12,7 @@
   "license": "Elastic License",
   "max_signals": 33,
   "name": "Microsoft IIS Service Account Password Dumped",
-  "query": "event.category:process AND event.type:(start OR process_started) AND (process.name:appcmd.exe OR process.pe.original_file_name:appcmd.exe) AND process.args:(/[lL][iI][sS][tT]/ AND /\\/[tT][eE][xX][tT]\\:[pP][aA][sS][sS][wW][oO][rR][dD]/)",
+  "query": "event.category:process AND event.type:(start OR process_started) AND (process.name:appcmd.exe OR process.pe.original_file_name:appcmd.exe or winlog.event_data.OriginalFileName:appcmd.exe) AND process.args:(/[lL][iI][sS][tT]/ AND /\\/[tT][eE][xX][tT]\\:[pP][aA][sS][sS][wW][oO][rR][dD]/)",
   "references": [
     "https://blog.netspi.com/decrypting-iis-passwords-to-break-out-of-the-dmz-part-1/"
   ],
@@ -21,7 +21,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Credential Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iis_connectionstrings_dumping.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iis_connectionstrings_dumping.json
index 2735fcbbd6130..f750a0f5594b4 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iis_connectionstrings_dumping.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iis_connectionstrings_dumping.json
@@ -12,7 +12,7 @@
   "license": "Elastic License",
   "max_signals": 33,
   "name": "Microsoft IIS Connection Strings Decryption",
-  "query": "event.category:process and event.type:(start or process_started) and (process.name:aspnet_regiis.exe or process.pe.original_file_name:aspnet_regiis.exe) and process.args:(connectionStrings and \"-pdf\")",
+  "query": "event.category:process and event.type:(start or process_started) and (process.name:aspnet_regiis.exe or process.pe.original_file_name:aspnet_regiis.exe or winlog.event_data.OriginalFileName:aspnet_regiis.exe) and process.args:(connectionStrings and \"-pdf\")",
   "references": [
     "https://blog.netspi.com/decrypting-iis-passwords-to-break-out-of-the-dmz-part-1/",
     "https://symantec-enterprise-blogs.security.com/blogs/threat-intelligence/greenbug-espionage-telco-south-asia"
@@ -22,7 +22,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Credential Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_kerberosdump_kcc.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_kerberosdump_kcc.json
index 4713d09f8adec..dda2f67c11663 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_kerberosdump_kcc.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_kerberosdump_kcc.json
@@ -21,7 +21,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "MacOS"
+    "Host",
+    "macOS",
+    "Threat Detection",
+    "Credential Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_key_vault_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_key_vault_modified.json
index a45591c73dcb3..33df4e5930066 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_key_vault_modified.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_key_vault_modified.json
@@ -24,9 +24,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
-    "SecOps",
     "Continuous Monitoring",
+    "SecOps",
     "Data Protection"
   ],
   "threat": [
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mimikatz_memssp_default_logs.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mimikatz_memssp_default_logs.json
index fa1f99eef7f00..ae9b63371a452 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mimikatz_memssp_default_logs.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mimikatz_memssp_default_logs.json
@@ -17,7 +17,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Credential Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_okta_brute_force_or_password_spraying.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_okta_brute_force_or_password_spraying.json
index c36f878792ccf..9e10dd6dae522 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_okta_brute_force_or_password_spraying.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_okta_brute_force_or_password_spraying.json
@@ -24,10 +24,11 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Identity and Access",
-    "Continuous Monitoring"
+    "Identity and Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_root_console_failure_brute_force.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_root_console_failure_brute_force.json
similarity index 96%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_root_console_failure_brute_force.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_root_console_failure_brute_force.json
index 5f7781be82efd..f65a7b11d11ad 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_root_console_failure_brute_force.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_root_console_failure_brute_force.json
@@ -23,11 +23,12 @@
   "rule_id": "4d50a94f-2844-43fa-8395-6afbd5e1c5ef",
   "severity": "high",
   "tags": [
+    "Elastic",
+    "Cloud",
     "AWS",
     "Continuous Monitoring",
-    "Elastic",
-    "Identity and Access",
-    "SecOps"
+    "SecOps",
+    "Identity and Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_secretsmanager_getsecretvalue.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_secretsmanager_getsecretvalue.json
index 879e93750df9c..a33593f701ba7 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_secretsmanager_getsecretvalue.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_secretsmanager_getsecretvalue.json
@@ -26,11 +26,12 @@
   "rule_id": "a00681e3-9ed6-447c-ab2c-be648821c622",
   "severity": "high",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Data Protection",
-    "Continuous Monitoring"
+    "Data Protection"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_storage_account_key_regenerated.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_storage_account_key_regenerated.json
index 2a3dc85294a9d..62e1aab700680 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_storage_account_key_regenerated.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_storage_account_key_regenerated.json
@@ -22,10 +22,11 @@
   "rule_id": "1e0b832e-957e-43ae-b319-db82d228c908",
   "severity": "low",
   "tags": [
-    "Azure",
     "Elastic",
-    "SecOps",
+    "Cloud",
+    "Azure",
     "Continuous Monitoring",
+    "SecOps",
     "Identity and Access"
   ],
   "threat": [
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_tcpdump_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_tcpdump_activity.json
index 306a38f5d2a28..67ab62e8d0ee5 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_tcpdump_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_tcpdump_activity.json
@@ -20,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Credential Access"
   ],
   "threat": [
     {
@@ -55,5 +58,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_adding_the_hidden_file_attribute_with_via_attribexe.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_adding_the_hidden_file_attribute_with_via_attribexe.json
index c80f24a21d958..a1ff4bfc890a1 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_adding_the_hidden_file_attribute_with_via_attribexe.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_adding_the_hidden_file_attribute_with_via_attribexe.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -52,5 +55,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_iptables_or_firewall.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_iptables_or_firewall.json
index 4d4f10bbaa599..b17e4979a885c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_iptables_or_firewall.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_iptables_or_firewall.json
@@ -17,7 +17,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_syslog_service.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_syslog_service.json
index 3c34b04a77a50..960000c91e4fa 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_syslog_service.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_syslog_service.json
@@ -17,7 +17,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_diagnostic_settings_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_diagnostic_settings_deletion.json
index 49d98813dc040..7721790b5cf97 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_diagnostic_settings_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_diagnostic_settings_deletion.json
@@ -23,9 +23,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
-    "SecOps",
     "Continuous Monitoring",
+    "SecOps",
     "Monitoring"
   ],
   "threat": [
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_base16_or_base32_encoding_or_decoding_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_base16_or_base32_encoding_or_decoding_activity.json
index 3cdfac92572b1..140e1ccd8e890 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_base16_or_base32_encoding_or_decoding_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_base16_or_base32_encoding_or_decoding_activity.json
@@ -20,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -55,5 +58,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_base64_encoding_or_decoding_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_base64_encoding_or_decoding_activity.json
index 2d26d867b8718..fa322fca5db8a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_base64_encoding_or_decoding_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_base64_encoding_or_decoding_activity.json
@@ -20,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -55,5 +58,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_clearing_windows_event_logs.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_clearing_windows_event_logs.json
index 60ce575148f4c..11d57b855f974 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_clearing_windows_event_logs.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_clearing_windows_event_logs.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_deleted.json
index 64261af2a3105..169f429a6dd26 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_deleted.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_deleted.json
@@ -25,11 +25,12 @@
   "rule_id": "7024e2a0-315d-4334-bb1a-441c593e16ab",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Logging",
-    "Continuous Monitoring"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_suspended.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_suspended.json
index 090073698026d..cbd040a7f7a30 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_suspended.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_suspended.json
@@ -25,11 +25,12 @@
   "rule_id": "1aa8fa52-44a7-4dae-b058-f3333b91c8d7",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Logging",
-    "Continuous Monitoring"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudwatch_alarm_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudwatch_alarm_deletion.json
index aeaf0a4168814..e18deb65c497b 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudwatch_alarm_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudwatch_alarm_deletion.json
@@ -25,11 +25,12 @@
   "rule_id": "f772ec8a-e182-483c-91d2-72058f76a44c",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_code_injection_conhost.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_code_injection_conhost.json
index 63c7ea12b3b6b..ed1b8978c6329 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_code_injection_conhost.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_code_injection_conhost.json
@@ -21,7 +21,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_config_service_rule_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_config_service_rule_deletion.json
index 268f52a8efd5e..b7d9321814fd7 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_config_service_rule_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_config_service_rule_deletion.json
@@ -25,11 +25,12 @@
   "rule_id": "7024e2a0-315d-4334-bb1a-552d604f27bc",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_configuration_recorder_stopped.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_configuration_recorder_stopped.json
index b926937450f5a..b28572deaf204 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_configuration_recorder_stopped.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_configuration_recorder_stopped.json
@@ -25,11 +25,12 @@
   "rule_id": "fbd44836-0d69-4004-a0b4-03c20370c435",
   "severity": "high",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cve_2020_0601.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cve_2020_0601.json
index 2abad3c255f15..3beb71763f1ae 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cve_2020_0601.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cve_2020_0601.json
@@ -15,7 +15,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -35,5 +38,5 @@
     }
   ],
   "type": "query",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_delete_volume_usn_journal_with_fsutil.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_delete_volume_usn_journal_with_fsutil.json
index 50213b9f1a42c..5fde3c462eded 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_delete_volume_usn_journal_with_fsutil.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_delete_volume_usn_journal_with_fsutil.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_deleting_backup_catalogs_with_wbadmin.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_deleting_backup_catalogs_with_wbadmin.json
index 026735f413eab..554ccc6972e5d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_deleting_backup_catalogs_with_wbadmin.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_deleting_backup_catalogs_with_wbadmin.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_deletion_of_bash_command_line_history.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_deletion_of_bash_command_line_history.json
index 85d8bdcb2582f..eef37499c8eb5 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_deletion_of_bash_command_line_history.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_deletion_of_bash_command_line_history.json
@@ -17,7 +17,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_selinux_attempt.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_selinux_attempt.json
index d107c0b262091..35476a76fd4b5 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_selinux_attempt.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_selinux_attempt.json
@@ -17,7 +17,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_windows_firewall_rules_with_netsh.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_windows_firewall_rules_with_netsh.json
index 6fbf9ca800f79..a69fde9f6a5cc 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_windows_firewall_rules_with_netsh.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_windows_firewall_rules_with_netsh.json
@@ -17,7 +17,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_dotnet_compiler_parent_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_dotnet_compiler_parent_process.json
similarity index 93%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_dotnet_compiler_parent_process.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_dotnet_compiler_parent_process.json
index 0a675bd7aab74..08cbb33710b26 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_dotnet_compiler_parent_process.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_dotnet_compiler_parent_process.json
@@ -17,7 +17,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_flow_log_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_flow_log_deletion.json
index 9f3d4e6b5e379..d36294684698e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_flow_log_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_flow_log_deletion.json
@@ -25,11 +25,12 @@
   "rule_id": "9395fd2c-9947-4472-86ef-4aceb2f7e872",
   "severity": "high",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Logging",
-    "Continuous Monitoring"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_network_acl_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_network_acl_deletion.json
index 6ecc9ad3d558d..b6ac9be800807 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_network_acl_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_network_acl_deletion.json
@@ -27,11 +27,12 @@
   "rule_id": "8623535c-1e17-44e1-aa97-7a0699c3037d",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Network",
-    "Continuous Monitoring"
+    "Network Security"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_encoding_or_decoding_files_via_certutil.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_encoding_or_decoding_files_via_certutil.json
index 0d47aab2c64bd..f00ac3f90527b 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_encoding_or_decoding_files_via_certutil.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_encoding_or_decoding_files_via_certutil.json
@@ -17,7 +17,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_event_hub_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_event_hub_deletion.json
index 29df07cced4d7..d09edf473c939 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_event_hub_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_event_hub_deletion.json
@@ -24,11 +24,12 @@
   "rule_id": "e0f36de1-0342-453d-95a9-a068b257b053",
   "severity": "medium",
   "tags": [
-    "Azure",
     "Elastic",
-    "SecOps",
+    "Cloud",
+    "Azure",
     "Continuous Monitoring",
-    "Logging"
+    "SecOps",
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_office_app.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_office_app.json
index a987c00b392ec..c41b3aad2f42c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_office_app.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_office_app.json
@@ -23,7 +23,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_script.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_script.json
index 0537f27bad463..a8e16d8bda238 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_script.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_script.json
@@ -20,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_system_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_system_process.json
index 11fdd128475dc..60c9a317bbb6c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_system_process.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_system_process.json
@@ -20,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_renamed.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_renamed.json
index a90e5ebc57800..5daab573db5bd 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_renamed.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_renamed.json
@@ -20,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_unusal_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_unusal_process.json
index 4f353a6ff9e6f..09247d2f21323 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_unusal_process.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_unusal_process.json
@@ -23,7 +23,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -43,5 +46,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_suspicious_explorer_winword.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_suspicious_explorer_winword.json
index 69d334cf13fdb..7d9f190ba7be2 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_suspicious_explorer_winword.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_suspicious_explorer_winword.json
@@ -11,13 +11,16 @@
   "language": "kuery",
   "license": "Elastic License",
   "name": "Potential DLL SideLoading via Trusted Microsoft Programs",
-  "query": "event.category:process and event.type:(start or process_started) and process.pe.original_file_name:(WinWord.exe or EXPLORER.EXE or w3wp.exe or DISM.EXE) and not (process.name:(winword.exe or WINWORD.EXE or explorer.exe or w3wp.exe or Dism.exe) or process.executable:(\"C:\\Windows\\explorer.exe\" or C\\:\\\\Program?Files\\\\Microsoft?Office\\\\root\\\\Office*\\\\WINWORD.EXE or C\\:\\\\Program?Files?\\(x86\\)\\\\Microsoft?Office\\\\root\\\\Office*\\\\WINWORD.EXE or \"C:\\Windows\\System32\\Dism.exe\" or \"C:\\Windows\\SysWOW64\\Dism.exe\" or \"C:\\Windows\\System32\\inetsrv\\w3wp.exe\"))",
+  "query": "event.category:process and event.type:(start or process_started) and (process.pe.original_file_name:(WinWord.exe or EXPLORER.EXE or w3wp.exe or DISM.EXE) or winlog.event_data.OriginalFileName:(WinWord.exe or EXPLORER.EXE or w3wp.exe or DISM.EXE)) and not (process.name:(winword.exe or WINWORD.EXE or explorer.exe or w3wp.exe or Dism.exe) or process.executable:(\"C:\\Windows\\explorer.exe\" or C\\:\\\\Program?Files\\\\Microsoft?Office\\\\root\\\\Office*\\\\WINWORD.EXE or C\\:\\\\Program?Files?\\(x86\\)\\\\Microsoft?Office\\\\root\\\\Office*\\\\WINWORD.EXE or \"C:\\Windows\\System32\\Dism.exe\" or \"C:\\Windows\\SysWOW64\\Dism.exe\" or \"C:\\Windows\\System32\\inetsrv\\w3wp.exe\"))",
   "risk_score": 73,
   "rule_id": "1160dcdb-0a0a-4a79-91d8-9b84616edebd",
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_via_trusted_developer_utilities.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_via_trusted_developer_utilities.json
index a1d14155cc3b3..7963c03699f78 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_via_trusted_developer_utilities.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_via_trusted_developer_utilities.json
@@ -7,7 +7,8 @@
     "These programs may be used by Windows developers but use by non-engineers is unusual."
   ],
   "index": [
-    "winlogbeat-*"
+    "winlogbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -18,7 +19,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_deletion_via_shred.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_deletion_via_shred.json
index 5b02f63a1c7f7..dc73b7bc1eb76 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_deletion_via_shred.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_deletion_via_shred.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_mod_writable_dir.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_mod_writable_dir.json
index 8ee2d4fda7bf8..b97e5c1d6a182 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_mod_writable_dir.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_mod_writable_dir.json
@@ -20,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -40,5 +43,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_firewall_policy_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_firewall_policy_deletion.json
index 759fc9d5ecb1f..69a123ba678fd 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_firewall_policy_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_firewall_policy_deletion.json
@@ -22,11 +22,12 @@
   "rule_id": "e02bd3ea-72c6-4181-ac2b-0f83d17ad969",
   "severity": "low",
   "tags": [
-    "Azure",
     "Elastic",
-    "SecOps",
+    "Cloud",
+    "Azure",
     "Continuous Monitoring",
-    "Network"
+    "SecOps",
+    "Network Security"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_created.json
index b80a5f0e17949..dc08dace20bfc 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_created.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_created.json
@@ -22,6 +22,7 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_deleted.json
index 64c8d01df47e9..7ee5af109f37b 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_deleted.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_deleted.json
@@ -22,6 +22,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_modified.json
index b2c0e259b45e0..b4107fb9f08fd 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_modified.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_modified.json
@@ -22,6 +22,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_bucket_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_bucket_deletion.json
index 62447b789d632..079a87b5c615b 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_bucket_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_bucket_deletion.json
@@ -23,10 +23,11 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
-    "Logging"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_sink_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_sink_deletion.json
index 0fc83070ffbb7..8466b618fab98 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_sink_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_sink_deletion.json
@@ -22,10 +22,11 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
-    "Logging"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_subscription_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_subscription_deletion.json
index 2ae47140b66a5..5b87b8722595c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_subscription_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_subscription_deletion.json
@@ -22,10 +22,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
-    "Logging"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_topic_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_topic_deletion.json
index f276af3e21862..5a681a35006a7 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_topic_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_topic_deletion.json
@@ -22,10 +22,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
-    "Logging"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_configuration_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_configuration_modified.json
index 3b18732137c32..5992beef9873e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_configuration_modified.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_configuration_modified.json
@@ -22,6 +22,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_permissions_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_permissions_modified.json
index ad6beb9383eea..0687bb1e5178a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_permissions_modified.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_permissions_modified.json
@@ -22,6 +22,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_guardduty_detector_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_guardduty_detector_deletion.json
index 3910b8e4039ad..50ee5a902b144 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_guardduty_detector_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_guardduty_detector_deletion.json
@@ -25,11 +25,12 @@
   "rule_id": "523116c0-d89d-4d7c-82c2-39e6845a78ef",
   "severity": "high",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hex_encoding_or_decoding_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hex_encoding_or_decoding_activity.json
index f5345b2276e8a..6d3d6f456da4c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hex_encoding_or_decoding_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hex_encoding_or_decoding_activity.json
@@ -20,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -55,5 +58,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hidden_file_dir_tmp.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hidden_file_dir_tmp.json
index e66968a50709e..c21c15909d82a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hidden_file_dir_tmp.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hidden_file_dir_tmp.json
@@ -21,7 +21,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -56,5 +59,5 @@
     }
   ],
   "type": "query",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_iis_httplogging_disabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_iis_httplogging_disabled.json
index 507260f04d016..7d75f50856125 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_iis_httplogging_disabled.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_iis_httplogging_disabled.json
@@ -12,13 +12,16 @@
   "license": "Elastic License",
   "max_signals": 33,
   "name": "IIS HTTP Logging Disabled",
-  "query": "event.category:process and event.type:(start or process_started) and (process.name:appcmd.exe or process.pe.original_file_name:appcmd.exe) and process.args:/dontLog\\:\\\"True\\\" and not process.parent.name:iissetup.exe",
+  "query": "event.category:process and event.type:(start or process_started) and (process.name:appcmd.exe or process.pe.original_file_name:appcmd.exe or winlog.event_data.OriginalFileName:appcmd.exe) and process.args:/dontLog\\:\\\"True\\\" and not process.parent.name:iissetup.exe",
   "risk_score": 73,
   "rule_id": "ebf1adea-ccf2-4943-8b96-7ab11ca173a5",
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_injection_msbuild.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_injection_msbuild.json
index 9abce01769e92..7978ef9004271 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_injection_msbuild.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_injection_msbuild.json
@@ -18,7 +18,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -53,5 +56,5 @@
     }
   ],
   "type": "query",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_installutil_beacon.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_installutil_beacon.json
similarity index 67%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_installutil_beacon.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_installutil_beacon.json
index 7437bf27141ec..231ed1b36dc0f 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_installutil_beacon.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_installutil_beacon.json
@@ -11,13 +11,16 @@
   "language": "eql",
   "license": "Elastic License",
   "name": "InstallUtil Process Making Network Connections",
-  "query": "/* this can be done without a sequence however, this does include more info on the process */\n\nsequence by process.entity_id\n  [process where event.type in (\"start\", \"process_started\") and process.name == \"installutil.exe\"]\n  [network where event.type == \"connection\" and process.name == \"installutil.exe\" and network.direction == \"outgoing\"]\n",
+  "query": "/* the benefit of doing this as an eql sequence vs kql is this will limit to alerting only on the first network connection */\n\nsequence by process.entity_id\n  [process where event.type in (\"start\", \"process_started\") and process.name : \"installutil.exe\"]\n  [network where event.type == \"connection\" and process.name : \"installutil.exe\" and network.direction == \"outgoing\"]\n",
   "risk_score": 21,
   "rule_id": "a13167f1-eec2-4015-9631-1fee60406dcf",
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kernel_module_removal.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kernel_module_removal.json
index ad751a1031437..5c38974b46525 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kernel_module_removal.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kernel_module_removal.json
@@ -23,7 +23,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -58,5 +61,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_as_elastic_endpoint_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_as_elastic_endpoint_process.json
index 8b7ef47443e2f..163c7e834ba34 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_as_elastic_endpoint_process.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_as_elastic_endpoint_process.json
@@ -17,7 +17,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_renamed_autoit.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_renamed_autoit.json
index cc964bfdd3e92..be83f8c41a2ea 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_renamed_autoit.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_renamed_autoit.json
@@ -11,13 +11,16 @@
   "language": "lucene",
   "license": "Elastic License",
   "name": "Renamed AutoIt Scripts Interpreter",
-  "query": "event.category:process AND event.type:(start OR process_started) AND process.pe.original_file_name:/[aA][uU][tT][oO][iI][tT]\\d\\.[eE][xX][eE]/ AND NOT process.name:/[aA][uU][tT][oO][iI][tT]\\d{1,3}\\.[eE][xX][eE]/",
+  "query": "event.category:process AND event.type:(start OR process_started) AND (process.pe.original_file_name:/[aA][uU][tT][oO][iI][tT]\\d\\.[eE][xX][eE]/ OR winlog.event_data.OriginalFileName:/[aA][uU][tT][oO][iI][tT]\\d\\.[eE][xX][eE]/) AND NOT process.name:/[aA][uU][tT][oO][iI][tT]\\d{1,3}\\.[eE][xX][eE]/",
   "risk_score": 47,
   "rule_id": "2e1e835d-01e5-48ca-b9fc-7a61f7f11902",
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_suspicious_werfault_childproc.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_suspicious_werfault_childproc.json
index 3000e7ac86daa..df0ecf1d534a1 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_suspicious_werfault_childproc.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_suspicious_werfault_childproc.json
@@ -24,7 +24,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_werfault.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_werfault.json
index db421146085ff..9f5615d466374 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_werfault.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_masquerading_werfault.json
@@ -24,7 +24,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_misc_lolbin_connecting_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_misc_lolbin_connecting_to_the_internet.json
index 5b5f69a0aef74..3d87720818ff5 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_misc_lolbin_connecting_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_misc_lolbin_connecting_to_the_internet.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -52,5 +55,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_modification_of_boot_config.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_modification_of_boot_config.json
index 6025fc5ca6452..84ccc52249622 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_modification_of_boot_config.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_modification_of_boot_config.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_msbuild_beacon_sequence.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_msbuild_beacon_sequence.json
similarity index 79%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_msbuild_beacon_sequence.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_msbuild_beacon_sequence.json
index 59295c3735a3a..0740e26d3bba6 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_msbuild_beacon_sequence.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_msbuild_beacon_sequence.json
@@ -11,13 +11,16 @@
   "language": "eql",
   "license": "Elastic License",
   "name": "MsBuild Network Connection Sequence",
-  "query": "sequence by process.entity_id\n  [process where event.type in (\"start\", \"process_started\") and process.name == \"MSBuild.exe\"]\n  [network where process.name == \"MSBuild.exe\" and\n     not (destination.address == \"127.0.0.1\" and source.address == \"127.0.0.1\")]\n",
+  "query": "sequence by process.entity_id\n  [process where event.type in (\"start\", \"process_started\") and process.name : \"MSBuild.exe\"]\n  [network where process.name : \"MSBuild.exe\" and\n     not (destination.ip == \"127.0.0.1\" and source.ip == \"127.0.0.1\")]\n",
   "risk_score": 21,
   "rule_id": "9dc6ed5d-62a9-4feb-a903-fafa1d33b8e9",
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_mshta_beacon.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_mshta_beacon.json
similarity index 69%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_mshta_beacon.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_mshta_beacon.json
index 105f536628777..fd19942a33d48 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_mshta_beacon.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_mshta_beacon.json
@@ -11,13 +11,16 @@
   "language": "eql",
   "license": "Elastic License",
   "name": "Mshta Making Network Connections",
-  "query": "sequence by process.entity_id with maxspan=2h\n  [process where event.type in (\"start\", \"process_started\") and process.name == \"mshta.exe\" and\n     process.parent.name != \"Microsoft.ConfigurationManagement.exe\" and\n     process.parent.executable not in (\"C:\\\\Amazon\\\\Amazon Assistant\\\\amazonAssistantService.exe\",\n                                       \"C:\\\\TeamViewer\\\\TeamViewer.exe\") and\n     process.args != \"ADSelfService_Enroll.hta\"]\n  [network where process.name == \"mshta.exe\"]\n",
+  "query": "sequence by process.entity_id with maxspan=2h\n  [process where event.type in (\"start\", \"process_started\") and process.name : \"mshta.exe\" and\n     not process.parent.name : \"Microsoft.ConfigurationManagement.exe\" and\n     not (process.parent.executable : \"C:\\\\Amazon\\\\Amazon Assistant\\\\amazonAssistantService.exe\" or\n          process.parent.executable : \"C:\\\\TeamViewer\\\\TeamViewer.exe\") and\n     not process.args : \"ADSelfService_Enroll.hta\"]\n  [network where process.name : \"mshta.exe\"]\n",
   "risk_score": 21,
   "rule_id": "c2d90150-0133-451c-a783-533e736c12d7",
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_msxsl_beacon.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_msxsl_beacon.json
similarity index 79%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_msxsl_beacon.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_msxsl_beacon.json
index 27704b3e182ed..c188387304214 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_msxsl_beacon.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_msxsl_beacon.json
@@ -11,13 +11,16 @@
   "language": "eql",
   "license": "Elastic License",
   "name": "MsXsl Making Network Connections",
-  "query": "sequence by process.entity_id\n  [process where event.type in (\"start\", \"process_started\") and process.name == \"msxsl.exe\"]\n  [network where event.type == \"connection\" and process.name == \"msxsl.exe\" and network.direction == \"outgoing\"]\n",
+  "query": "sequence by process.entity_id\n  [process where event.type in (\"start\", \"process_started\") and process.name : \"msxsl.exe\"]\n  [network where event.type == \"connection\" and process.name : \"msxsl.exe\" and network.direction == \"outgoing\"]\n",
   "risk_score": 21,
   "rule_id": "870d1753-1078-403e-92d4-735f142edcca",
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_connection_from_windows_binary.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_connection_from_windows_binary.json
new file mode 100644
index 0000000000000..4e1d0cad0b5da
--- /dev/null
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_connection_from_windows_binary.json
@@ -0,0 +1,44 @@
+{
+  "author": [
+    "Elastic"
+  ],
+  "description": "Identifies network activity from unexpected system applications. This may indicate adversarial activity as these applications are often leveraged by adversaries to execute code and evade detection.",
+  "from": "now-9m",
+  "index": [
+    "logs-endpoint.events.*",
+    "winlogbeat-*"
+  ],
+  "language": "eql",
+  "license": "Elastic License",
+  "name": "Unusual Network Activity from a Windows System Binary",
+  "query": "sequence by process.entity_id with maxspan=5m\n  [process where event.type in (\"start\", \"process_started\") and\n\n     /* known applocker bypasses */\n     (process.name : \"bginfo.exe\" or\n      process.name : \"cdb.exe\" or\n      process.name : \"control.exe\" or\n      process.name : \"cmstp.exe\" or\n      process.name : \"csi.exe\" or\n      process.name : \"dnx.exe\" or\n      process.name : \"fsi.exe\" or\n      process.name : \"ieexec.exe\" or\n      process.name : \"iexpress.exe\" or\n      process.name : \"installutil.exe\" or\n      process.name : \"Microsoft.Workflow.Compiler.exe\" or\n      process.name : \"MSBuild.exe\" or\n      process.name : \"msdt.exe\" or\n      process.name : \"mshta.exe\" or\n      process.name : \"msiexec.exe\" or\n      process.name : \"msxsl.exe\" or\n      process.name : \"odbcconf.exe\" or\n      process.name : \"rcsi.exe\" or\n      process.name : \"regsvr32.exe\" or\n      process.name : \"xwizard.exe\")]\n  [network where event.type == \"connection\" and\n     (process.name : \"bginfo.exe\" or\n      process.name : \"cdb.exe\" or\n      process.name : \"control.exe\" or\n      process.name : \"cmstp.exe\" or\n      process.name : \"csi.exe\" or\n      process.name : \"dnx.exe\" or\n      process.name : \"fsi.exe\" or\n      process.name : \"ieexec.exe\" or\n      process.name : \"iexpress.exe\" or\n      process.name : \"installutil.exe\" or\n      process.name : \"Microsoft.Workflow.Compiler.exe\" or\n      process.name : \"MSBuild.exe\" or\n      process.name : \"msdt.exe\" or\n      process.name : \"mshta.exe\" or\n      process.name : \"msiexec.exe\" or\n      process.name : \"msxsl.exe\" or\n      process.name : \"odbcconf.exe\" or\n      process.name : \"rcsi.exe\" or\n      process.name : \"regsvr32.exe\" or\n      process.name : \"xwizard.exe\")]\n",
+  "risk_score": 21,
+  "rule_id": "1fe3b299-fbb5-4657-a937-1d746f2c711a",
+  "severity": "medium",
+  "tags": [
+    "Elastic",
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
+  ],
+  "threat": [
+    {
+      "framework": "MITRE ATT&CK",
+      "tactic": {
+        "id": "TA0005",
+        "name": "Defense Evasion",
+        "reference": "https://attack.mitre.org/tactics/TA0005/"
+      },
+      "technique": [
+        {
+          "id": "T1127",
+          "name": "Trusted Developer Utilities Proxy Execution",
+          "reference": "https://attack.mitre.org/techniques/T1127/"
+        }
+      ]
+    }
+  ],
+  "type": "eql",
+  "version": 1
+}
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_watcher_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_watcher_deletion.json
index 09bbba5a049e4..0e6d9172eb2c1 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_watcher_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_watcher_deletion.json
@@ -23,10 +23,11 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
-    "SecOps",
     "Continuous Monitoring",
-    "Network"
+    "SecOps",
+    "Network Security"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_reg_beacon.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_reg_beacon.json
similarity index 66%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_reg_beacon.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_reg_beacon.json
index 332c719eaa41d..aa4f9985f6e2c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_reg_beacon.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_reg_beacon.json
@@ -11,13 +11,16 @@
   "language": "eql",
   "license": "Elastic License",
   "name": "Registration Tool Making Network Connections",
-  "query": "sequence by process.entity_id\n  [process where event.type in (\"start\", \"process_started\") and\n     process.name in (\"regasm.exe\", \"regsvcs.exe\", \"regsvr32.exe\")]\n  [network where event.type == \"connection\" and process.name in (\"regasm.exe\", \"regsvcs.exe\", \"regsvr32.exe\")]\nuntil\n  [process where event.type == \"end\" and process.name in (\"regasm.exe\", \"regsvcs.exe\", \"regsvr32.exe\")]\n",
+  "query": "sequence by process.entity_id\n  [process where event.type in (\"start\", \"process_started\") and\n     (process.name : \"RegAsm.exe\" or process.name : \"regsvcs.exe\" or process.name : \"regsvr32.exe\")]\n  [network where event.type == \"connection\" and\n     (process.name : \"RegAsm.exe\" or process.name : \"regsvcs.exe\" or process.name : \"regsvr32.exe\")]\nuntil\n  [process where event.type == \"end\" and\n     (process.name : \"RegAsm.exe\" or process.name : \"regsvcs.exe\" or process.name : \"regsvr32.exe\")]\n",
   "risk_score": 21,
   "rule_id": "6d3456a5-4a42-49d1-aaf2-7b1fd475b2c6",
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/evasion_rundll32_no_arguments.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_rundll32_no_arguments.json
similarity index 61%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/evasion_rundll32_no_arguments.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_rundll32_no_arguments.json
index 06fad7e0f630b..2950b792219b6 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/evasion_rundll32_no_arguments.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_rundll32_no_arguments.json
@@ -11,13 +11,16 @@
   "language": "eql",
   "license": "Elastic License",
   "name": "Unusual Child Processes of RunDLL32",
-  "query": "sequence with maxspan=1h\n  [process where event.type in (\"start\", \"process_started\") and\n     (process.name == \"rundll32.exe\" or process.pe.original_file_name == \"rundll32.exe\") and\n\n     /* zero arguments excluding the binary itself (and accounting for when the binary may not be logged in args) */\n     ((process.args == \"rundll32.exe\" and process.args_count == 1) or\n      (process.args != \"rundll32.exe\" and process.args_count == 0))\n\n  ] by process.entity_id\n  [process where event.type in (\"start\", \"process_started\") and\n     (process.name == \"rundll32.exe\" or process.pe.original_file_name == \"rundll32.exe\")\n  ] by process.parent.entity_id\n",
+  "query": "sequence with maxspan=1h\n  [process where event.type in (\"start\", \"process_started\") and\n                                    /* uncomment once in winlogbeat */\n     (process.name : \"rundll32.exe\" /* or process.pe.original_file_name == \"RUNDLL32.EXE\" */ ) and\n     process.args_count < 2\n  ] by process.entity_id\n  [process where event.type in (\"start\", \"process_started\") and\n                                    /* uncomment once in winlogbeat */\n     (process.name : \"rundll32.exe\" /* or process.pe.original_file_name == \"RUNDLL32.EXE\" */ )\n  ] by process.parent.entity_id\n",
   "risk_score": 21,
   "rule_id": "f036953a-4615-4707-a1ca-dc53bf69dcd5",
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_rundll32_sequence.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_rundll32_sequence.json
similarity index 67%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_rundll32_sequence.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_rundll32_sequence.json
index 6f465325039a6..c022d0a603858 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/c2_rundll32_sequence.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_rundll32_sequence.json
@@ -11,13 +11,16 @@
   "language": "eql",
   "license": "Elastic License",
   "name": "Unusual Network Connection Sequence via RunDLL32",
-  "query": "sequence by process.entity_id with maxspan=2h\n  [process where event.type in (\"start\", \"process_started\") and\n     (process.name == \"rundll32.exe\" or process.pe.original_file_name == \"rundll32.exe\") and\n\n     /* zero arguments excluding the binary itself (and accounting for when the binary may not be logged in args) */\n     ((process.args == \"rundll32.exe\" and process.args_count == 1) or\n      (process.args != \"rundll32.exe\" and process.args_count == 0))]\n\n  [network where event.type == \"connection\" and\n     (process.name == \"rundll32.exe\" or process.pe.original_file_name == \"rundll32.exe\")]\n",
+  "query": "sequence by process.entity_id with maxspan=2h\n  [process where event.type in (\"start\", \"process_started\") and\n                                    /* uncomment once in winlogbeat */\n     (process.name : \"rundll32.exe\" /* or process.pe.original_file_name == \"RUNDLL32.EXE\" */ ) and\n     process.args_count < 2]\n  [network where event.type == \"connection\" and\n                                     /* uncomment once in winlogbeat */\n     (process.name : \"rundll32.exe\" /* or process.pe.original_file_name == \"RUNDLL32.EXE\" */ )]\n",
   "risk_score": 21,
   "rule_id": "2b347f66-6739-4ae3-bd94-195036dde8b3",
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_s3_bucket_configuration_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_s3_bucket_configuration_deletion.json
index adbe310b784e5..6cfdf40781397 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_s3_bucket_configuration_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_s3_bucket_configuration_deletion.json
@@ -28,11 +28,12 @@
   "rule_id": "227dc608-e558-43d9-b521-150772250bae",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Asset Visibility",
-    "Continuous Monitoring"
+    "Asset Visibility"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_sdelete_like_filename_rename.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_sdelete_like_filename_rename.json
index ec3030d44ff29..6fea9a3c78945 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_sdelete_like_filename_rename.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_sdelete_like_filename_rename.json
@@ -18,7 +18,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_managedcode_host_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_managedcode_host_process.json
index 1bb3f26c0298f..85eac81808a71 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_managedcode_host_process.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_managedcode_host_process.json
@@ -20,7 +20,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_okta_user_password_reset_or_unlock_attempts.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_okta_user_password_reset_or_unlock_attempts.json
similarity index 99%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_okta_user_password_reset_or_unlock_attempts.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_okta_user_password_reset_or_unlock_attempts.json
index 5f115416fa032..fedeaca68ab64 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_suspicious_okta_user_password_reset_or_unlock_attempts.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_okta_user_password_reset_or_unlock_attempts.json
@@ -25,6 +25,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/evasion_suspicious_scrobj_load.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_scrobj_load.json
similarity index 51%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/evasion_suspicious_scrobj_load.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_scrobj_load.json
index 7880b86533b53..16364f590cd0e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/evasion_suspicious_scrobj_load.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_scrobj_load.json
@@ -11,13 +11,16 @@
   "language": "eql",
   "license": "Elastic License",
   "name": "Windows Suspicious Script Object Execution",
-  "query": "sequence by process.entity_id with maxspan=2m\n  [process where event.type in (\"start\", \"process_started\") and\n     /* process.code_signature.* fields need to be populated for 7.10 */\n     process.code_signature.subject_name == \"Microsoft Corporation\" and process.code_signature.trusted == true and\n     process.name not in (\"cscript.exe\",\n                          \"iexplore.exe\",\n                          \"MicrosoftEdge.exe\",\n                          \"msiexec.exe\",\n                          \"smartscreen.exe\",\n                          \"taskhostw.exe\",\n                          \"w3wp.exe\",\n                          \"wscript.exe\")]\n  [library where event.type == \"start\" and file.name == \"scrobj.dll\"]\n",
+  "query": "/* add winlogbeat-* when process.code_signature.* fields are populated */\n\nsequence by process.entity_id with maxspan=2m\n  [process where event.type in (\"start\", \"process_started\") and\n     /* uncomment once in winlogbeat */\n     /* process.code_signature.subject_name == \"Microsoft Corporation\" and process.code_signature.trusted == true and */\n     not (process.name : \"cscript.exe\" or\n          process.name : \"iexplore.exe\" or\n          process.name : \"MicrosoftEdge.exe\" or\n          process.name : \"msiexec.exe\" or\n          process.name : \"smartscreen.exe\" or\n          process.name : \"taskhostw.exe\" or\n          process.name : \"w3wp.exe\" or\n          process.name : \"wscript.exe\")]\n  [library where event.type == \"start\" and file.name : \"scrobj.dll\"]\n",
   "risk_score": 21,
   "rule_id": "4ed678a9-3a4f-41fb-9fea-f85a6e0a0dff",
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/evasion_suspicious_wmi_script.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_wmi_script.json
similarity index 59%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/evasion_suspicious_wmi_script.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_wmi_script.json
index 943471f5801c2..e922416264359 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/evasion_suspicious_wmi_script.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_wmi_script.json
@@ -5,19 +5,21 @@
   "description": "Identifies WMIC whitelisting bypass techniques by alerting on suspicious execution of scripts. When WMIC loads scripting libraries it may be indicative of a whitelist bypass.",
   "from": "now-9m",
   "index": [
-    "logs-endpoint.events.*",
-    "winlogbeat-*"
+    "logs-endpoint.events.*"
   ],
   "language": "eql",
   "license": "Elastic License",
   "name": "Suspicious WMIC XSL Script Execution",
-  "query": "/* lots of wildcards in the args\n   need to verify args cleanup is accurate\n*/\n\nsequence by process.entity_id with maxspan=2m\n[process where event.type in (\"start\", \"process_started\") and\n   (process.name == \"wmic.exe\" or process.pe.original_file_name == \"wmic.exe\") and\n   wildcard(process.args, \"format*:*\", \"/format*:*\", \"*-format*:*\") and\n   not process.args in (\"/format:table\", \"/format:table\") or wildcard(process.args, \"format*:*\")]\n[library where event.type == \"start\" and file.name in (\"jscript.dll\", \"vbscript.dll\")]\n",
+  "query": "sequence by process.entity_id with maxspan=2m\n[process where event.type in (\"start\", \"process_started\") and\n   (process.name : \"WMIC.exe\" or process.pe.original_file_name == \"wmic.exe\") and\n   wildcard(process.args, \"format*:*\", \"/format*:*\", \"*-format*:*\") and\n   not wildcard(process.command_line, \"* /format:table *\")]\n[library where event.type == \"start\" and file.name in (\"jscript.dll\", \"vbscript.dll\")]\n",
   "risk_score": 21,
   "rule_id": "7f370d54-c0eb-4270-ac5a-9a6020585dc6",
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_zoom_child_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_zoom_child_process.json
index 7b08f5a565424..f3c20e5251184 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_zoom_child_process.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_zoom_child_process.json
@@ -20,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_system_critical_proc_abnormal_file_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_system_critical_proc_abnormal_file_activity.json
index 6fea3a75c8e62..31702332d7cd4 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_system_critical_proc_abnormal_file_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_system_critical_proc_abnormal_file_activity.json
@@ -17,7 +17,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unusual_system_vp_child_program.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unusual_system_vp_child_program.json
index 4efec948f49a7..65439d6d653b6 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unusual_system_vp_child_program.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unusual_system_vp_child_program.json
@@ -17,7 +17,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_via_filter_manager.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_via_filter_manager.json
index 210e9c778afef..3092ea653aa4b 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_via_filter_manager.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_via_filter_manager.json
@@ -4,7 +4,8 @@
   ],
   "description": "The Filter Manager Control Program (fltMC.exe) binary may be abused by adversaries to unload a filter driver and evade defenses.",
   "index": [
-    "winlogbeat-*"
+    "winlogbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -15,7 +16,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_volume_shadow_copy_deletion_via_vssadmin.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_volume_shadow_copy_deletion_via_vssadmin.json
index 8a504281b03f7..493ee919000dc 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_volume_shadow_copy_deletion_via_vssadmin.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_volume_shadow_copy_deletion_via_vssadmin.json
@@ -17,7 +17,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_volume_shadow_copy_deletion_via_wmic.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_volume_shadow_copy_deletion_via_wmic.json
index 2ae938bb34104..49a68f4bfcf66 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_volume_shadow_copy_deletion_via_wmic.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_volume_shadow_copy_deletion_via_wmic.json
@@ -17,7 +17,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Defense Evasion"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_acl_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_acl_deletion.json
index 32101029fb107..86ed9e2f9c042 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_acl_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_acl_deletion.json
@@ -25,11 +25,12 @@
   "rule_id": "91d04cd4-47a9-4334-ab14-084abe274d49",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Network",
-    "Continuous Monitoring"
+    "Network Security"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_rule_or_rule_group_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_rule_or_rule_group_deletion.json
index a08c05d0d6ca7..302e89d416f4b 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_rule_or_rule_group_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_rule_or_rule_group_deletion.json
@@ -25,11 +25,12 @@
   "rule_id": "5beaebc1-cc13-4bfc-9949-776f9e0dc318",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Network",
-    "Continuous Monitoring"
+    "Network Security"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_blob_container_access_mod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_blob_container_access_mod.json
index 7e601c9928d08..16db02338de55 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_blob_container_access_mod.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_blob_container_access_mod.json
@@ -23,9 +23,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
-    "SecOps",
     "Continuous Monitoring",
+    "SecOps",
     "Asset Visibility"
   ],
   "threat": [
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_kernel_module_enumeration.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_kernel_module_enumeration.json
index af9c4b5409964..f2681f5501af0 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_kernel_module_enumeration.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_kernel_module_enumeration.json
@@ -20,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Discovery"
   ],
   "threat": [
     {
@@ -40,5 +43,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_net_command_system_account.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_net_command_system_account.json
index 96c300cfde016..682434f28f745 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_net_command_system_account.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_net_command_system_account.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Discovery"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_post_exploitation_public_ip_reconnaissance.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_post_exploitation_public_ip_reconnaissance.json
index 952d70ee3589a..36e95cf4ade41 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_post_exploitation_public_ip_reconnaissance.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_post_exploitation_public_ip_reconnaissance.json
@@ -24,8 +24,8 @@
   "tags": [
     "Elastic",
     "Network",
-    "Threat Detection, Preventing and Hunting",
-    "Post-Execution"
+    "Threat Detection",
+    "Discovery"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_process_discovery_via_tasklist_command.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_process_discovery_via_tasklist_command.json
index c2d95de4129f9..59ddc00d6525d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_process_discovery_via_tasklist_command.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_process_discovery_via_tasklist_command.json
@@ -7,7 +7,8 @@
     "Administrators may use the tasklist command to display a list of currently running processes. By itself, it does not indicate malicious activity. After obtaining a foothold, it's possible adversaries may use discovery commands like tasklist to get information about running processes."
   ],
   "index": [
-    "winlogbeat-*"
+    "winlogbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -18,7 +19,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Discovery"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_virtual_machine_fingerprinting.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_virtual_machine_fingerprinting.json
index d913a92e2ee0e..66b744667f568 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_virtual_machine_fingerprinting.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_virtual_machine_fingerprinting.json
@@ -20,7 +20,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Discovery"
   ],
   "threat": [
     {
@@ -40,5 +43,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_whoami_command_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_whoami_command_activity.json
index cb330879be9b3..2e577e44c960e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_whoami_command_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_whoami_command_activity.json
@@ -7,7 +7,8 @@
     "Some normal use of this program, at varying levels of frequency, may originate from scripts, automation tools and frameworks. Usage by non-engineers and ordinary users is unusual."
   ],
   "index": [
-    "winlogbeat-*"
+    "winlogbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -18,7 +19,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Discovery"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_whoami_commmand.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_whoami_commmand.json
index a8b34362d9579..ddf309b377609 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_whoami_commmand.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_whoami_commmand.json
@@ -20,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Discovery"
   ],
   "threat": [
     {
@@ -40,5 +43,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint.json
index f3acc5d3a2b5e..d6e7419391f9c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint.json
@@ -60,7 +60,7 @@
   ],
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "timestamp_override": "event.ingested",
   "type": "query",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_adversary_behavior_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_adversary_behavior_detected.json
index b3bac305bc1f1..8084067b3a6d2 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_adversary_behavior_detected.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_adversary_behavior_detected.json
@@ -17,7 +17,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_dumping_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_dumping_detected.json
index 2f91c1fe813f9..9c28d065b322d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_dumping_detected.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_dumping_detected.json
@@ -17,7 +17,7 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_dumping_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_dumping_prevented.json
index 75488c2d3a5ed..352712e38f42d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_dumping_prevented.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_dumping_prevented.json
@@ -17,7 +17,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_manipulation_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_manipulation_detected.json
index adc29d9106774..259bcd51aeb3e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_manipulation_detected.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_manipulation_detected.json
@@ -17,7 +17,7 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_manipulation_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_manipulation_prevented.json
index 99def69978a48..19348062b10f1 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_manipulation_prevented.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_cred_manipulation_prevented.json
@@ -17,7 +17,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_exploit_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_exploit_detected.json
index 80eb3ce637f30..2fd3aaa0d8a57 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_exploit_detected.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_exploit_detected.json
@@ -17,7 +17,7 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_exploit_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_exploit_prevented.json
index 50444904654de..8f90e1162546b 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_exploit_prevented.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_exploit_prevented.json
@@ -17,7 +17,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_malware_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_malware_detected.json
index bb2ddf92a83e7..3d740f8b7064f 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_malware_detected.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_malware_detected.json
@@ -17,7 +17,7 @@
   "severity": "critical",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_malware_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_malware_prevented.json
index fae8a3a0ab5a6..33195c7fcbecc 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_malware_prevented.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_malware_prevented.json
@@ -17,7 +17,7 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_permission_theft_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_permission_theft_detected.json
index 821c3b0d8a63b..fac13a6d358dd 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_permission_theft_detected.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_permission_theft_detected.json
@@ -17,7 +17,7 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_permission_theft_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_permission_theft_prevented.json
index e38afe19e7d38..a2d8700076c23 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_permission_theft_prevented.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_permission_theft_prevented.json
@@ -17,7 +17,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_process_injection_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_process_injection_detected.json
index 52eb3c2d96bf7..ef4f29067b0c5 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_process_injection_detected.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_process_injection_detected.json
@@ -17,7 +17,7 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_process_injection_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_process_injection_prevented.json
index 76aff15e1588c..b22751e35c053 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_process_injection_prevented.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_process_injection_prevented.json
@@ -17,7 +17,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_ransomware_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_ransomware_detected.json
index 29efdd910904d..3b973f42bbca5 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_ransomware_detected.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_ransomware_detected.json
@@ -17,7 +17,7 @@
   "severity": "critical",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_ransomware_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_ransomware_prevented.json
index c603e503c5dad..b6458b73e8015 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_ransomware_prevented.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endpoint_ransomware_prevented.json
@@ -17,7 +17,7 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Endpoint"
+    "Endpoint Security"
   ],
   "type": "query",
   "version": 4
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/escalation_uac_sdclt.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/escalation_uac_sdclt.json
deleted file mode 100644
index 843ba3401b4e4..0000000000000
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/escalation_uac_sdclt.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
-  "author": [
-    "Elastic"
-  ],
-  "description": "Identifies User Account Control (UAC) bypass via sdclt.exe. Attackers bypass UAC to stealthily execute code with elevated permissions.",
-  "from": "now-9m",
-  "index": [
-    "logs-endpoint.events.*",
-    "winlogbeat-*"
-  ],
-  "language": "eql",
-  "license": "Elastic License",
-  "name": "Bypass UAC via Sdclt",
-  "query": "sequence with maxspan=1m\n  [process where event.type in (\"start\", \"process_started\") and process.name == \"sdclt.exe\" and\n     /* process.code_signature.* fields need to be populated for 7.10 */\n     process.code_signature.subject_name == \"Microsoft Corporation\" and process.code_signature.trusted == true and\n     process.args == \"/kickoffelev\"\n  ] by process.entity_id\n  [process where event.type in (\"start\", \"process_started\") and process.parent.name == \"sdclt.exe\" and\n     process.executable not in (\"C:\\\\Windows\\\\System32\\\\sdclt.exe\",\n                                \"C:\\\\Windows\\\\System32\\\\control.exe\",\n                                \"C:\\\\Windows\\\\SysWOW64\\\\sdclt.exe\",\n                                \"C:\\\\Windows\\\\SysWOW64\\\\control.exe\")\n  ] by process.parent.entity_id\n",
-  "risk_score": 21,
-  "rule_id": "9b54e002-034a-47ac-9307-ad12c03fa900",
-  "severity": "high",
-  "tags": [
-    "Elastic",
-    "Windows"
-  ],
-  "threat": [
-    {
-      "framework": "MITRE ATT&CK",
-      "tactic": {
-        "id": "TA0004",
-        "name": "Privilege Escalation",
-        "reference": "https://attack.mitre.org/tactics/TA0004/"
-      },
-      "technique": [
-        {
-          "id": "T1088",
-          "name": "Bypass User Account Control",
-          "reference": "https://attack.mitre.org/techniques/T1088/"
-        }
-      ]
-    }
-  ],
-  "type": "eql",
-  "version": 1
-}
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_prompt_connecting_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_prompt_connecting_to_the_internet.json
index e9989fe50019e..d73b1a4cab008 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_prompt_connecting_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_prompt_connecting_to_the_internet.json
@@ -20,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_shell_started_by_powershell.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_shell_started_by_powershell.json
index bb252b1416832..220a7f94dce9a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_shell_started_by_powershell.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_shell_started_by_powershell.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_shell_started_by_svchost.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_shell_started_by_svchost.json
index aeae5518fece1..d6b1e67b11982 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_shell_started_by_svchost.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_shell_started_by_svchost.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_shell_started_by_unusual_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_shell_started_by_unusual_process.json
index 577bee1ffe6de..566a5963c122a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_shell_started_by_unusual_process.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_shell_started_by_unusual_process.json
@@ -17,7 +17,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_virtual_machine.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_virtual_machine.json
index 5e7852e1c1b13..31c4d488c6960 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_virtual_machine.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_virtual_machine.json
@@ -24,11 +24,12 @@
   "rule_id": "60884af6-f553-4a6c-af13-300047455491",
   "severity": "medium",
   "tags": [
-    "Azure",
     "Elastic",
-    "SecOps",
+    "Cloud",
+    "Azure",
     "Continuous Monitoring",
-    "Logging"
+    "SecOps",
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_html_help_executable_program_connecting_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_html_help_executable_program_connecting_to_the_internet.json
index 963c6b2e53ed6..d33f2287c7d8b 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_html_help_executable_program_connecting_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_html_help_executable_program_connecting_to_the_internet.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
@@ -52,5 +55,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_local_service_commands.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_local_service_commands.json
index 7b20cefdc67f0..693ca83e387b3 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_local_service_commands.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_local_service_commands.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_ms_office_written_file.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_ms_office_written_file.json
index 35d7a7c969ee7..2db46080a4e75 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_ms_office_written_file.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_ms_office_written_file.json
@@ -11,13 +11,16 @@
   "language": "eql",
   "license": "Elastic License",
   "name": "Execution of File Written or Modified by Microsoft Office",
-  "query": "sequence with maxspan=2h\n  [file where event.type != \"delete\" and file.extension == \"exe\" and\n     process.name in (\"winword.exe\",\n                      \"excel.exe\",\n                      \"outlook.exe\",\n                      \"powerpnt.exe\",\n                      \"eqnedt32.exe\",\n                      \"fltldr.exe\",\n                      \"mspub.exe\",\n                      \"msaccess.exe\")\n  ] by host.id, file.path\n  [process where event.type in (\"start\", \"process_started\")] by host.id, process.executable\n",
+  "query": "sequence with maxspan=2h\n  [file where event.type != \"deletion\" and file.extension : \"exe\" and\n     (process.name : \"WINWORD.EXE\" or\n      process.name : \"EXCEL.EXE\" or\n      process.name : \"OUTLOOK.EXE\" or\n      process.name : \"POWERPNT.EXE\" or\n      process.name : \"eqnedt32.exe\" or\n      process.name : \"fltldr.exe\" or\n      process.name : \"MSPUB.EXE\" or\n      process.name : \"MSACCESS.EXE\")\n  ] by host.id, file.path\n  [process where event.type in (\"start\", \"process_started\")] by host.id, process.executable\n",
   "risk_score": 21,
   "rule_id": "0d8ad79f-9025-45d8-80c1-4f0cd3c5e8e5",
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_msbuild_making_network_connections.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_msbuild_making_network_connections.json
index fcbbfbdb3d686..7fd2933fe46f1 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_msbuild_making_network_connections.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_msbuild_making_network_connections.json
@@ -17,7 +17,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_mshta_making_network_connections.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_mshta_making_network_connections.json
index 7af823070889f..9b863c2ed5ee4 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_mshta_making_network_connections.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_mshta_making_network_connections.json
@@ -20,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
@@ -40,5 +43,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_msxsl_network.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_msxsl_network.json
index 1dc75575636fb..17987218af0ae 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_msxsl_network.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_msxsl_network.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_pdf_written_file.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_pdf_written_file.json
index 3963b3d594902..a807052cf7b0d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_pdf_written_file.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_pdf_written_file.json
@@ -11,13 +11,16 @@
   "language": "eql",
   "license": "Elastic License",
   "name": "Execution of File Written or Modified by PDF Reader",
-  "query": "sequence with maxspan=2h\n  [file where event.type != \"delete\" and file.extension == \"exe\" and\n     process.name in (\"acrord32.exe\", \"rdrcef.exe\", \"foxitphantomPDF.exe\", \"foxitreader.exe\") and\n     file.name not in (\"foxitphantomPDF.exe\",\n                       \"FoxitPhantomPDFUpdater.exe\",\n                       \"foxitreader.exe\",\n                       \"FoxitReaderUpdater.exe\",\n                       \"acrord32.exe\",\n                       \"rdrcef.exe\")\n  ] by host.id, file.path\n  [process where event.type in (\"start\", \"process_started\")] by host.id, process.executable\n",
+  "query": "sequence with maxspan=2h\n  [file where event.type != \"deletion\" and file.extension : \"exe\" and\n     (process.name : \"AcroRd32.exe\" or\n      process.name : \"rdrcef.exe\" or\n      process.name : \"FoxitPhantomPDF.exe\" or\n      process.name : \"FoxitReader.exe\") and\n     not (file.name : \"FoxitPhantomPDF.exe\" or\n          file.name : \"FoxitPhantomPDFUpdater.exe\" or\n          file.name : \"FoxitReader.exe\" or\n          file.name : \"FoxitReaderUpdater.exe\" or\n          file.name : \"AcroRd32.exe\" or\n          file.name : \"rdrcef.exe\")\n  ] by host.id, file.path\n  [process where event.type in (\"start\", \"process_started\")] by host.id, process.executable\n",
   "risk_score": 21,
   "rule_id": "1defdd62-cd8d-426e-a246-81a37751bb2b",
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_perl_tty_shell.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_perl_tty_shell.json
index 4502f42bbb4c4..ee6cee941bef2 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_perl_tty_shell.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_perl_tty_shell.json
@@ -17,7 +17,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_psexec_lateral_movement_command.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_psexec_lateral_movement_command.json
index f647d8d00e084..8505a837ad591 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_psexec_lateral_movement_command.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_psexec_lateral_movement_command.json
@@ -20,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
@@ -55,5 +58,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_python_tty_shell.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_python_tty_shell.json
index 0e8b5f0218d00..151c3fbb8df46 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_python_tty_shell.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_python_tty_shell.json
@@ -17,7 +17,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_register_server_program_connecting_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_register_server_program_connecting_to_the_internet.json
index 899bb1c20e711..bf1a30f11137e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_register_server_program_connecting_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_register_server_program_connecting_to_the_internet.json
@@ -20,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_script_executing_powershell.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_script_executing_powershell.json
index 6d7f11f01fae0..843cf322e5849 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_script_executing_powershell.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_script_executing_powershell.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_ms_office_child_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_ms_office_child_process.json
index 005a0c38c8a8b..90c60ceea37ab 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_ms_office_child_process.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_ms_office_child_process.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_ms_outlook_child_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_ms_outlook_child_process.json
index 74e21c7d17479..d5ee8fa818367 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_ms_outlook_child_process.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_ms_outlook_child_process.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_pdf_reader.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_pdf_reader.json
index adf1a76bfb901..bf37f5a803e58 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_pdf_reader.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_pdf_reader.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_suspicious_psexesvc.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_psexesvc.json
similarity index 76%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_suspicious_psexesvc.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_psexesvc.json
index 51396fb5995f6..205b5148f2fb4 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_suspicious_psexesvc.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_suspicious_psexesvc.json
@@ -11,13 +11,16 @@
   "language": "kuery",
   "license": "Elastic License",
   "name": "Suspicious Process Execution via Renamed PsExec Executable",
-  "query": "event.category:process and event.type:(start or process_started) and process.pe.original_file_name:(psexesvc.exe or PSEXESVC.exe) and process.parent.name:services.exe and not process.name:(psexesvc.exe or PSEXESVC.exe)",
+  "query": "event.category:process and event.type:(start or process_started) and (process.pe.original_file_name:(psexesvc.exe or PSEXESVC.exe) or winlog.event_data.OriginalFileName:(psexesvc.exe or PSEXESVC.exe)) and process.parent.name:services.exe and not process.name:(psexesvc.exe or PSEXESVC.exe)",
   "risk_score": 47,
   "rule_id": "e2f9fdf5-8076-45ad-9427-41e0e03dc9c2",
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_dns_service_children.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_dns_service_children.json
index 96305b2197bfc..52e67b0c7bcff 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_dns_service_children.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_dns_service_children.json
@@ -7,7 +7,8 @@
     "Werfault.exe will legitimately spawn when dns.exe crashes, but the DNS service is very stable and so this is a low occurring event. Denial of Service (DoS) attempts by intentionally crashing the service will also cause werfault.exe to spawn."
   ],
   "index": [
-    "winlogbeat-*"
+    "winlogbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -24,7 +25,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_dns_service_file_writes.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_dns_service_file_writes.json
index c175ecbfa78b6..229fc28beee9c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_dns_service_file_writes.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_dns_service_file_writes.json
@@ -4,7 +4,8 @@
   ],
   "description": "Identifies an unexpected file being modified by dns.exe, the process responsible for Windows DNS Server services, which may indicate activity related to remote code execution or other forms of exploitation.",
   "index": [
-    "winlogbeat-*"
+    "winlogbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -20,7 +21,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_network_connection_via_rundll32.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_network_connection_via_rundll32.json
index 1104159350655..2763f69e1f8e8 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_network_connection_via_rundll32.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_network_connection_via_rundll32.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 5
+  "version": 6
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_process_network_connection.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_process_network_connection.json
index 774e8e9189ced..877c489b0d187 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_process_network_connection.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_unusual_process_network_connection.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_compiled_html_file.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_compiled_html_file.json
index fe3e110830420..276e5c18335f5 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_compiled_html_file.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_compiled_html_file.json
@@ -7,7 +7,8 @@
     "The HTML Help executable program (hh.exe) runs whenever a user clicks a compiled help (.chm) file or menu item that opens the help file inside the Help Viewer. This is not always malicious, but adversaries may abuse this technology to conceal malicious code."
   ],
   "index": [
-    "winlogbeat-*"
+    "winlogbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -18,7 +19,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_hidden_shell_conhost.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_hidden_shell_conhost.json
index 7fbf962469f71..b6f6502e603aa 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_hidden_shell_conhost.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_hidden_shell_conhost.json
@@ -20,7 +20,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_net_com_assemblies.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_net_com_assemblies.json
index d9dcbfe25a4c2..0a21599c31a4a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_net_com_assemblies.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_net_com_assemblies.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
@@ -52,5 +55,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_system_manager.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_system_manager.json
index 081ebcb518999..13493a90e3e50 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_system_manager.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_system_manager.json
@@ -24,11 +24,12 @@
   "rule_id": "37b211e8-4e2f-440f-86d8-06cc8f158cfa",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Logging",
-    "Continuous Monitoring"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_xp_cmdshell_mssql_stored_procedure.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_xp_cmdshell_mssql_stored_procedure.json
index 8769e641fad90..91097b2050d17 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_xp_cmdshell_mssql_stored_procedure.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_xp_cmdshell_mssql_stored_procedure.json
@@ -17,7 +17,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_wpad_exploitation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_wpad_exploitation.json
index 03c4482b60340..a09bce5119ecf 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_wpad_exploitation.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_wpad_exploitation.json
@@ -5,19 +5,21 @@
   "description": "Identifies probable exploitation of the Web Proxy Auto-Discovery Protocol (WPAD) service. Attackers who have access to the local network or upstream DNS traffic can inject malicious JavaScript to the WPAD service which can lead to a full system compromise.",
   "from": "now-9m",
   "index": [
-    "logs-endpoint.events.*",
-    "winlogbeat-*"
+    "logs-endpoint.events.*"
   ],
   "language": "eql",
   "license": "Elastic License",
   "name": "WPAD Service Exploit",
-  "query": "/* preference would be to use user.sid rather than domain+name, once it is available in ECS + datasources */\n\nsequence with maxspan=5s\n  [process where event.type in (\"start\", \"process_started\") and process.name == \"svchost.exe\" and\n     user.domain == \"NT AUTHORITY\" and user.name == \"LOCAL SERVICE\"] by process.entity_id\n  [network where network.protocol == \"dns\" and process.name == \"svchost.exe\" and\n     dns.question.name == \"wpad\" and process.name == \"svchost.exe\"] by process.entity_id\n  [network where event.type == \"connection\" and process.name == \"svchost.exe\"\n     and network.direction == \"outgoing\" and destination.port == 80] by process.entity_id\n  [library where event.type == \"start\" and process.name == \"svchost.exe\" and\n     file.name == \"jscript.dll\" and process.name == \"svchost.exe\"] by process.entity_id\n  [process where event.type in (\"start\", \"process_started\") and\n     process.parent.name == \"svchost.exe\"] by process.parent.entity_id\n",
+  "query": "/* preference would be to use user.sid rather than domain+name, once it is available in ECS + datasources */\n\nsequence with maxspan=5s\n  [process where event.type in (\"start\", \"process_started\") and process.name : \"svchost.exe\" and\n     user.domain == \"NT AUTHORITY\" and user.name == \"LOCAL SERVICE\"] by process.entity_id\n  [network where network.protocol == \"dns\" and process.name : \"svchost.exe\" and\n     dns.question.name : \"wpad\" and process.name : \"svchost.exe\"] by process.entity_id\n  [network where event.type == \"connection\" and process.name : \"svchost.exe\"\n     and network.direction == \"outgoing\" and destination.port == 80] by process.entity_id\n  [library where event.type == \"start\" and process.name : \"svchost.exe\" and\n     file.name : \"jscript.dll\" and process.name : \"svchost.exe\"] by process.entity_id\n  [process where event.type in (\"start\", \"process_started\") and\n     process.parent.name : \"svchost.exe\"] by process.parent.entity_id\n",
   "risk_score": 21,
   "rule_id": "ec328da1-d5df-482b-866c-4a435692b1f3",
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Execution"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_ec2_snapshot_change_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_ec2_snapshot_change_activity.json
index fc18a516be0f4..abf64d55ab99a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_ec2_snapshot_change_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_ec2_snapshot_change_activity.json
@@ -25,11 +25,12 @@
   "rule_id": "98fd7407-0bd5-5817-cda0-3fcc33113a56",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Asset Visibility",
-    "Continuous Monitoring"
+    "Asset Visibility"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_gcp_logging_sink_modification.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_gcp_logging_sink_modification.json
index 4e8954c3441cd..5e3cc2da2f871 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_gcp_logging_sink_modification.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_gcp_logging_sink_modification.json
@@ -22,10 +22,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
-    "Logging"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/external_alerts.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/external_alerts.json
index 6bc14f4e5af8a..a8a86348a1019 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/external_alerts.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/external_alerts.json
@@ -54,9 +54,14 @@
     }
   ],
   "tags": [
-    "Elastic"
+    "Elastic",
+    "Network",
+    "Windows",
+    "APM",
+    "macOS",
+    "Linux"
   ],
   "timestamp_override": "event.ingested",
   "type": "query",
-  "version": 1
+  "version": 2
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_attempt_to_revoke_okta_api_token.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_attempt_to_revoke_okta_api_token.json
index f9d71a2e1cbff..f2ad30fa26020 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_attempt_to_revoke_okta_api_token.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_attempt_to_revoke_okta_api_token.json
@@ -24,10 +24,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_azure_automation_runbook_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_azure_automation_runbook_deleted.json
index 662709774f5ba..f474357cc6e2c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_azure_automation_runbook_deleted.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_azure_automation_runbook_deleted.json
@@ -23,6 +23,7 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudtrail_logging_updated.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudtrail_logging_updated.json
index c648ae1ea4b5b..d7f4c2b19bc0f 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudtrail_logging_updated.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudtrail_logging_updated.json
@@ -25,11 +25,12 @@
   "rule_id": "3e002465-876f-4f04-b016-84ef48ce7e5d",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Logging",
-    "Continuous Monitoring"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_group_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_group_deletion.json
index f7e9077c14314..ae978f6564d67 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_group_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_group_deletion.json
@@ -25,11 +25,12 @@
   "rule_id": "68a7a5a5-a2fc-4a76-ba9f-26849de881b4",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Logging",
-    "Continuous Monitoring"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_stream_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_stream_deletion.json
index b50efb21e42f0..7b985fdb6f693 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_stream_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_stream_deletion.json
@@ -25,11 +25,12 @@
   "rule_id": "d624f0ae-3dd1-4856-9aad-ccfe4d4bfa17",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Logging",
-    "Continuous Monitoring"
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_ec2_disable_ebs_encryption.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_ec2_disable_ebs_encryption.json
index 370a65c31e7c1..c60619e894717 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_ec2_disable_ebs_encryption.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_ec2_disable_ebs_encryption.json
@@ -26,11 +26,12 @@
   "rule_id": "bb9b13b2-1700-48a8-a750-b43b0a72ab69",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Data Protection",
-    "Continuous Monitoring"
+    "Data Protection"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_iam_role_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_iam_role_deletion.json
index 2c67be7408d1d..09a9996680155 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_iam_role_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_iam_role_deletion.json
@@ -22,6 +22,7 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_deleted.json
index 2aa702e5ca4d1..9d34f31c1700d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_deleted.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_deleted.json
@@ -22,6 +22,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_disabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_disabled.json
index 9b5188f43633d..606ebd1e6128e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_disabled.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_disabled.json
@@ -22,6 +22,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_storage_bucket_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_storage_bucket_deleted.json
index 6adad4b687de7..859c59ff8a325 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_storage_bucket_deleted.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_storage_bucket_deleted.json
@@ -22,6 +22,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_network_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_network_deleted.json
index c5dc9f25f893f..7f702f11a9515 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_network_deleted.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_network_deleted.json
@@ -22,6 +22,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_created.json
index 5e8fea09befc4..1da90189f96b8 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_created.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_created.json
@@ -23,6 +23,7 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_deleted.json
index 8482e0efbb036..c379f07f021a6 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_deleted.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_deleted.json
@@ -23,6 +23,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_hosts_file_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_hosts_file_modified.json
index bf04626dee277..5d7e0bec4332c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_hosts_file_modified.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_hosts_file_modified.json
@@ -22,9 +22,12 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
     "Windows",
-    "macOS"
+    "macOS",
+    "Threat Detection",
+    "Impact"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_deactivate_mfa_device.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_deactivate_mfa_device.json
index ca5cfd4ae596b..83e184d9bf805 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_deactivate_mfa_device.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_deactivate_mfa_device.json
@@ -25,11 +25,12 @@
   "rule_id": "d8fc1cca-93ed-43c1-bbb6-c0dd3eff2958",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_group_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_group_deletion.json
index 00a10772d4d9a..6212aa70747a5 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_group_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_group_deletion.json
@@ -25,11 +25,12 @@
   "rule_id": "867616ec-41e5-4edc-ada2-ab13ab45de8a",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_possible_okta_dos_attack.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_possible_okta_dos_attack.json
index 9bc44bf4e6da9..d1852478c666f 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_possible_okta_dos_attack.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_possible_okta_dos_attack.json
@@ -21,10 +21,11 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_cluster_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_cluster_deletion.json
index 829c244dd45c0..116483173564e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_cluster_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_cluster_deletion.json
@@ -27,11 +27,12 @@
   "rule_id": "9055ece6-2689-4224-a0e0-b04881e1f8ad",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Asset Visibility",
-    "Continuous Monitoring"
+    "Asset Visibility"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_instance_cluster_stoppage.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_instance_cluster_stoppage.json
index 68459d0e777b9..3227649149380 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_instance_cluster_stoppage.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_instance_cluster_stoppage.json
@@ -27,11 +27,12 @@
   "rule_id": "ecf2b32c-e221-4bd4-aa3b-c7d59b3bc01d",
   "severity": "medium",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Asset Visibility",
-    "Continuous Monitoring"
+    "Asset Visibility"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_resource_group_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_resource_group_deletion.json
index a0c56c19b964e..8086c09e4b174 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_resource_group_deletion.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_resource_group_deletion.json
@@ -23,10 +23,11 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
-    "SecOps",
     "Continuous Monitoring",
-    "Logging"
+    "SecOps",
+    "Log Auditing"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts
index 6e376930617de..5fec97e83bad4 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts
@@ -221,14 +221,14 @@ import rule209 from './credential_access_okta_brute_force_or_password_spraying.j
 import rule210 from './execution_unusual_dns_service_children.json';
 import rule211 from './execution_unusual_dns_service_file_writes.json';
 import rule212 from './lateral_movement_dns_server_overflow.json';
-import rule213 from './initial_access_root_console_failure_brute_force.json';
+import rule213 from './credential_access_root_console_failure_brute_force.json';
 import rule214 from './initial_access_unsecure_elasticsearch_node.json';
 import rule215 from './credential_access_domain_backup_dpapi_private_keys.json';
-import rule216 from './lateral_movement_gpo_schtask_service_creation.json';
-import rule217 from './credential_access_kerberosdump_kcc.json';
-import rule218 from './defense_evasion_execution_suspicious_psexesvc.json';
-import rule219 from './execution_via_xp_cmdshell_mssql_stored_procedure.json';
-import rule220 from './exfiltration_compress_credentials_keychains.json';
+import rule216 from './persistence_gpo_schtask_service_creation.json';
+import rule217 from './credential_access_compress_credentials_keychains.json';
+import rule218 from './credential_access_kerberosdump_kcc.json';
+import rule219 from './execution_suspicious_psexesvc.json';
+import rule220 from './execution_via_xp_cmdshell_mssql_stored_procedure.json';
 import rule221 from './privilege_escalation_printspooler_service_suspicious_file.json';
 import rule222 from './privilege_escalation_printspooler_suspicious_spl_file.json';
 import rule223 from './defense_evasion_azure_diagnostic_settings_deletion.json';
@@ -250,16 +250,16 @@ import rule238 from './persistence_azure_automation_webhook_created.json';
 import rule239 from './privilege_escalation_uac_bypass_diskcleanup_hijack.json';
 import rule240 from './credential_access_attempts_to_brute_force_okta_user_account.json';
 import rule241 from './credential_access_storage_account_key_regenerated.json';
-import rule242 from './credential_access_suspicious_okta_user_password_reset_or_unlock_attempts.json';
+import rule242 from './defense_evasion_suspicious_okta_user_password_reset_or_unlock_attempts.json';
 import rule243 from './defense_evasion_system_critical_proc_abnormal_file_activity.json';
 import rule244 from './defense_evasion_unusual_system_vp_child_program.json';
-import rule245 from './defense_evasion_mfa_disabled_for_azure_user.json';
-import rule246 from './discovery_blob_container_access_mod.json';
+import rule245 from './discovery_blob_container_access_mod.json';
+import rule246 from './persistence_mfa_disabled_for_azure_user.json';
 import rule247 from './persistence_user_added_as_owner_for_azure_application.json';
 import rule248 from './persistence_user_added_as_owner_for_azure_service_principal.json';
-import rule249 from './defense_evasion_suspicious_managedcode_host_process.json';
-import rule250 from './execution_command_shell_started_by_unusual_process.json';
-import rule251 from './execution_suspicious_dotnet_compiler_parent_process.json';
+import rule249 from './defense_evasion_dotnet_compiler_parent_process.json';
+import rule250 from './defense_evasion_suspicious_managedcode_host_process.json';
+import rule251 from './execution_command_shell_started_by_unusual_process.json';
 import rule252 from './defense_evasion_masquerading_as_elastic_endpoint_process.json';
 import rule253 from './defense_evasion_masquerading_suspicious_werfault_childproc.json';
 import rule254 from './defense_evasion_masquerading_werfault.json';
@@ -268,28 +268,28 @@ import rule256 from './credential_access_mimikatz_memssp_default_logs.json';
 import rule257 from './defense_evasion_code_injection_conhost.json';
 import rule258 from './defense_evasion_network_watcher_deletion.json';
 import rule259 from './initial_access_external_guest_user_invite.json';
-import rule260 from './defense_evasion_azure_conditional_access_policy_modified.json';
-import rule261 from './defense_evasion_azure_privileged_identity_management_role_modified.json';
-import rule262 from './defense_evasion_masquerading_renamed_autoit.json';
-import rule263 from './impact_azure_automation_runbook_deleted.json';
-import rule264 from './initial_access_consent_grant_attack_via_azure_registered_application.json';
-import rule265 from './c2_installutil_beacon.json';
-import rule266 from './c2_msbuild_beacon_sequence.json';
-import rule267 from './c2_mshta_beacon.json';
-import rule268 from './c2_msxsl_beacon.json';
-import rule269 from './c2_network_connection_from_windows_binary.json';
-import rule270 from './c2_reg_beacon.json';
-import rule271 from './c2_rundll32_sequence.json';
-import rule272 from './command_and_control_teamviewer_remote_file_copy.json';
-import rule273 from './escalation_uac_sdclt.json';
-import rule274 from './evasion_rundll32_no_arguments.json';
-import rule275 from './evasion_suspicious_scrobj_load.json';
-import rule276 from './evasion_suspicious_wmi_script.json';
-import rule277 from './execution_ms_office_written_file.json';
-import rule278 from './execution_pdf_written_file.json';
-import rule279 from './execution_wpad_exploitation.json';
-import rule280 from './lateral_movement_cmd_service.json';
-import rule281 from './persistence_app_compat_shim.json';
+import rule260 from './defense_evasion_masquerading_renamed_autoit.json';
+import rule261 from './impact_azure_automation_runbook_deleted.json';
+import rule262 from './initial_access_consent_grant_attack_via_azure_registered_application.json';
+import rule263 from './persistence_azure_conditional_access_policy_modified.json';
+import rule264 from './persistence_azure_privileged_identity_management_role_modified.json';
+import rule265 from './command_and_control_teamviewer_remote_file_copy.json';
+import rule266 from './defense_evasion_installutil_beacon.json';
+import rule267 from './defense_evasion_msbuild_beacon_sequence.json';
+import rule268 from './defense_evasion_mshta_beacon.json';
+import rule269 from './defense_evasion_msxsl_beacon.json';
+import rule270 from './defense_evasion_network_connection_from_windows_binary.json';
+import rule271 from './defense_evasion_reg_beacon.json';
+import rule272 from './defense_evasion_rundll32_no_arguments.json';
+import rule273 from './defense_evasion_rundll32_sequence.json';
+import rule274 from './defense_evasion_suspicious_scrobj_load.json';
+import rule275 from './defense_evasion_suspicious_wmi_script.json';
+import rule276 from './execution_ms_office_written_file.json';
+import rule277 from './execution_pdf_written_file.json';
+import rule278 from './execution_wpad_exploitation.json';
+import rule279 from './lateral_movement_cmd_service.json';
+import rule280 from './persistence_app_compat_shim.json';
+import rule281 from './privilege_escalation_uac_sdclt.json';
 import rule282 from './command_and_control_remote_file_copy_desktopimgdownldr.json';
 import rule283 from './command_and_control_remote_file_copy_mpcmdrun.json';
 import rule284 from './defense_evasion_execution_suspicious_explorer_winword.json';
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_consent_grant_attack_via_azure_registered_application.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_consent_grant_attack_via_azure_registered_application.json
index 8147859fa4e6f..1dab4e8df71b4 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_consent_grant_attack_via_azure_registered_application.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_consent_grant_attack_via_azure_registered_application.json
@@ -20,6 +20,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_console_login_root.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_console_login_root.json
index 621881e264138..1d6f5b2c90f26 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_console_login_root.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_console_login_root.json
@@ -24,11 +24,12 @@
   "rule_id": "e2a67480-3b79-403d-96e3-fdd2992c50ef",
   "severity": "high",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Identity and Access",
-    "Continuous Monitoring"
+    "Identity and Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_external_guest_user_invite.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_external_guest_user_invite.json
index 392e0ec745fc2..455fc3c762978 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_external_guest_user_invite.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_external_guest_user_invite.json
@@ -23,9 +23,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
-    "SecOps",
     "Continuous Monitoring",
+    "SecOps",
     "Identity and Access"
   ],
   "threat": [
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_gcp_iam_custom_role_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_gcp_iam_custom_role_creation.json
index 0eab41ad8c4bd..ff7ad0e8d29a2 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_gcp_iam_custom_role_creation.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_gcp_iam_custom_role_creation.json
@@ -22,6 +22,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_password_recovery.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_password_recovery.json
index 2f0eed31d05be..13279ea170358 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_password_recovery.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_password_recovery.json
@@ -24,11 +24,12 @@
   "rule_id": "69c420e8-6c9e-4d28-86c0-8a2be2d1e78c",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Identity and Access",
-    "Continuous Monitoring"
+    "Identity and Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rdp_remote_desktop_protocol_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rdp_remote_desktop_protocol_to_the_internet.json
index 15c3c81a551bd..ce0f44713523f 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rdp_remote_desktop_protocol_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rdp_remote_desktop_protocol_to_the_internet.json
@@ -8,7 +8,8 @@
   ],
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -19,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Initial Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_from_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_from_the_internet.json
index 7c61f95f9e9f3..b8f3e01823312 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_from_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_from_the_internet.json
@@ -5,7 +5,8 @@
   "description": "This rule detects network events that may indicate the use of RPC traffic from the Internet. RPC is commonly used by system administrators to remotely control a system for maintenance or to use shared resources. It should almost never be directly exposed to the Internet, as it is frequently targeted and exploited by threat actors as an initial access or back-door vector.",
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -16,7 +17,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Initial Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_to_the_internet.json
index e8da93ed9d1c7..e8e4ea4eb3746 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_to_the_internet.json
@@ -5,7 +5,8 @@
   "description": "This rule detects network events that may indicate the use of RPC traffic to the Internet. RPC is commonly used by system administrators to remotely control a system for maintenance or to use shared resources. It should almost never be directly exposed to the Internet, as it is frequently targeted and exploited by threat actors as an initial access or back-door vector.",
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -16,7 +17,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Initial Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_smb_windows_file_sharing_activity_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_smb_windows_file_sharing_activity_to_the_internet.json
index aff8a415b7e35..fec0f308a8d27 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_smb_windows_file_sharing_activity_to_the_internet.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_smb_windows_file_sharing_activity_to_the_internet.json
@@ -5,7 +5,8 @@
   "description": "This rule detects network events that may indicate the use of Windows file sharing (also called SMB or CIFS) traffic to the Internet. SMB is commonly used within networks to share files, printers, and other system resources amongst trusted systems. It should almost never be directly exposed to the Internet, as it is frequently targeted and exploited by threat actors as an initial access or back-door vector or for data exfiltration.",
   "index": [
     "filebeat-*",
-    "packetbeat-*"
+    "packetbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -16,7 +17,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Network"
+    "Host",
+    "Network",
+    "Threat Detection",
+    "Initial Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_suspicious_activity_reported_by_okta_user.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_suspicious_activity_reported_by_okta_user.json
index 24837084c8381..5b1946dc7c07d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_suspicious_activity_reported_by_okta_user.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_suspicious_activity_reported_by_okta_user.json
@@ -24,10 +24,11 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_unsecure_elasticsearch_node.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_unsecure_elasticsearch_node.json
index e6d718a23eb96..a577a3413e5df 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_unsecure_elasticsearch_node.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_unsecure_elasticsearch_node.json
@@ -23,7 +23,9 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Network"
+    "Network",
+    "Threat Detection",
+    "Initial Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_cmd_service.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_cmd_service.json
index bd14db77b9fe9..f4e137663762a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_cmd_service.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_cmd_service.json
@@ -11,13 +11,16 @@
   "language": "eql",
   "license": "Elastic License",
   "name": "Service Command Lateral Movement",
-  "query": "/* dependent on a wildcard for remote path */\n\nsequence by process.entity_id with maxspan=1m\n  [process where event.type in (\"start\", \"process_started\") and\n     (process.name == \"sc.exe\" or process.pe.original_file_name == \"sc.exe\") and\n     wildcard(process.args, \"\\\\\\\\*\") and wildcard(process.args, \"binPath*\", \"binpath*\") and\n     process.args in (\"create\", \"config\", \"failure\", \"start\")]\n  [network where event.type == \"connection\" and process.name == \"sc.exe\" and destination.address != \"127.0.0.1\"]\n",
+  "query": "sequence by process.entity_id with maxspan=1m\n  [process where event.type in (\"start\", \"process_started\") and\n                               /* uncomment once in winlogbeat */\n     (process.name == \"sc.exe\" /* or process.pe.original_file_name == \"sc.exe\" */ ) and\n                                                   /* case insensitive */\n      wildcard(process.args, \"\\\\\\\\*\") and wildcard(process.args, \"binPath=*\", \"binpath=*\") and \n      (process.args : \"create\" or\n       process.args : \"config\" or\n       process.args : \"failure\" or\n       process.args : \"start\")]\n  [network where event.type == \"connection\" and process.name : \"sc.exe\" and destination.ip != \"127.0.0.1\"]\n",
   "risk_score": 21,
   "rule_id": "d61cbcf8-1bc1-4cff-85ba-e7b21c5beedc",
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Lateral Movement"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_direct_outbound_smb_connection.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_direct_outbound_smb_connection.json
index e4014b22a6c09..39f45a736383a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_direct_outbound_smb_connection.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_direct_outbound_smb_connection.json
@@ -17,7 +17,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Lateral Movement"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_dns_server_overflow.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_dns_server_overflow.json
index 2a86dcac12e7b..052d0de3ef79e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_dns_server_overflow.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_dns_server_overflow.json
@@ -26,7 +26,8 @@
   "tags": [
     "Elastic",
     "Network",
-    "Windows"
+    "Threat Detection",
+    "Lateral Movement"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_remote_ssh_login_enabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_remote_ssh_login_enabled.json
index f1ce68abf8302..149dab112929c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_remote_ssh_login_enabled.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_remote_ssh_login_enabled.json
@@ -21,7 +21,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "MacOS"
+    "Host",
+    "macOS",
+    "Threat Detection",
+    "Lateral Movement"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_external.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_external.json
index e4804329c0f30..ff62251a465f7 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_external.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_external.json
@@ -20,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Lateral Movement"
   ],
   "threat": [
     {
@@ -40,5 +43,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_internal.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_internal.json
index 30312987d166c..bb6c03e9410e5 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_internal.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_internal.json
@@ -20,7 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Lateral Movement"
   ],
   "threat": [
     {
@@ -40,5 +43,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json
index 3a5c4d9e69d49..775d201cd1808 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json
@@ -23,8 +23,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection"
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json
index 63c82c5662df6..510eecb9d2fee 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json
@@ -23,8 +23,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection"
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json
index 99d087fe675a6..a81567740590d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json
@@ -23,7 +23,9 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection"
   ],
   "type": "query",
   "version": 5
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json
index bce10f640691b..ebe884debc9a0 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json
@@ -25,8 +25,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection"
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json
index 5d9e338425bda..76866f67d7288 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json
@@ -23,8 +23,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection"
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json
index bd019c9a80c4c..cc744614d68af 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json
@@ -23,8 +23,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection"
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json
index f0bbc892d7d9c..1662d63066feb 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json
@@ -20,8 +20,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection"
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json
index fac03d31b57bf..07cd9e4a065b3 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json
@@ -23,8 +23,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection"
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json
index c1b782d612ccb..06be108db2f14 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json
@@ -23,8 +23,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection"
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_error_message_spike.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_error_message_spike.json
index 0730c421cf5f2..890b777751a03 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_error_message_spike.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_error_message_spike.json
@@ -20,10 +20,11 @@
   "rule_id": "78d3d8d9-b476-451d-a9e0-7a5addd70670",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
     "ML"
   ],
   "type": "machine_learning",
-  "version": 1
+  "version": 2
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_error_code.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_error_code.json
index 8003cdd7504c7..62254d970ca7e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_error_code.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_error_code.json
@@ -20,10 +20,11 @@
   "rule_id": "19de8096-e2b0-4bd8-80c9-34a820813fff",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
     "ML"
   ],
   "type": "machine_learning",
-  "version": 1
+  "version": 2
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_city.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_city.json
index 2c54dbd03daba..5c1189c989bac 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_city.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_city.json
@@ -20,10 +20,11 @@
   "rule_id": "809b70d3-e2c3-455e-af1b-2626a5a1a276",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
     "ML"
   ],
   "type": "machine_learning",
-  "version": 1
+  "version": 2
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_country.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_country.json
index 68cbf4979a933..149ebd1a84fd4 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_country.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_country.json
@@ -20,10 +20,11 @@
   "rule_id": "dca28dee-c999-400f-b640-50a081cc0fd1",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
     "ML"
   ],
   "type": "machine_learning",
-  "version": 1
+  "version": 2
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_user.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_user.json
index e4ec651e71934..a8c0bce169432 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_user.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_cloudtrail_rare_method_by_user.json
@@ -20,10 +20,11 @@
   "rule_id": "ac706eae-d5ec-4b14-b4fd-e8ba8086f0e1",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
     "ML"
   ],
   "type": "machine_learning",
-  "version": 1
+  "version": 2
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_compiler_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_compiler_activity.json
index eb764c5e40817..592bd723e1a0c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_compiler_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_compiler_activity.json
@@ -17,7 +17,9 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "type": "machine_learning",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_kernel_module_arguments.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_kernel_module_arguments.json
index d289e0ba6f008..52a1d6dd5c60a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_kernel_module_arguments.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_kernel_module_arguments.json
@@ -20,7 +20,9 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "threat": [
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_process.json
index c1cc619164b1f..ec033a609cac1 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_process.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_process.json
@@ -11,13 +11,15 @@
   "interval": "15m",
   "license": "Elastic License",
   "machine_learning_job_id": "linux_rare_metadata_process",
-  "name": "Unusual Process Calling the Metadata Service",
+  "name": "Unusual Linux Process Calling the Metadata Service",
   "risk_score": 21,
   "rule_id": "9d302377-d226-4e12-b54c-1906b5aec4f6",
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "type": "machine_learning",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_user.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_user.json
index 59a04dd54dd89..a4a6b38bd32b8 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_user.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_user.json
@@ -17,7 +17,9 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "type": "machine_learning",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_activity.json
index bf86f78fe3e72..04df4adab8525 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_activity.json
@@ -18,9 +18,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_port_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_port_activity.json
index a588a6f5bcb0a..c5a0891a7bbc4 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_port_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_port_activity.json
@@ -20,9 +20,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_service.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_service.json
index 5c56845024eb2..81dff605dc779 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_service.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_service.json
@@ -20,9 +20,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_url_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_url_activity.json
index 3b3f751dfc60b..5336c31d4a741 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_url_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_url_activity.json
@@ -20,9 +20,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_process_all_hosts.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_process_all_hosts.json
index 8475410735f34..04d112c26e886 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_process_all_hosts.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_process_all_hosts.json
@@ -21,9 +21,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_sudo_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_sudo_activity.json
index 8f03b24a6bd18..57d5260d111db 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_sudo_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_sudo_activity.json
@@ -17,7 +17,9 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "threat": [
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_user_name.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_user_name.json
index 3e4b1f15fdce4..3f889dc529317 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_user_name.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_user_name.json
@@ -21,9 +21,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_information_discovery.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_information_discovery.json
index 40f117c6a5708..cdd1ee8d46653 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_information_discovery.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_information_discovery.json
@@ -17,7 +17,9 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "threat": [
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_network_configuration_discovery.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_network_configuration_discovery.json
index 326024114f145..b143293ac995b 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_network_configuration_discovery.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_network_configuration_discovery.json
@@ -17,7 +17,9 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "threat": [
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_network_connection_discovery.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_network_connection_discovery.json
index 881a2f9fa3410..ffab1c9eb8495 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_network_connection_discovery.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_network_connection_discovery.json
@@ -17,7 +17,9 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "threat": [
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_process_discovery.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_process_discovery.json
index 66859e2f9ccbf..69d2940029011 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_process_discovery.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_process_discovery.json
@@ -17,7 +17,9 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "threat": [
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_user_discovery.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_user_discovery.json
index 4437334b0aa1f..b5c5e66af6e7e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_user_discovery.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_system_user_discovery.json
@@ -17,7 +17,9 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "threat": [
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_dns_tunneling.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_dns_tunneling.json
index 1352fde91b59b..fbce00ebaf5a3 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_dns_tunneling.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_dns_tunneling.json
@@ -20,9 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Packetbeat"
+    "Network",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_dns_question.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_dns_question.json
index b16e67052a212..744e9fbfc18d8 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_dns_question.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_dns_question.json
@@ -20,9 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Packetbeat"
+    "Network",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_server_domain.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_server_domain.json
index a8971300fe11b..a672985655859 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_server_domain.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_server_domain.json
@@ -20,9 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Packetbeat"
+    "Network",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_urls.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_urls.json
index 469f5d741ef6e..5600fbe74c7fc 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_urls.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_urls.json
@@ -20,9 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Packetbeat"
+    "Network",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_user_agent.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_user_agent.json
index ebcf4f987e9de..5cce9c63fd88e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_user_agent.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_packetbeat_rare_user_agent.json
@@ -20,9 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Packetbeat"
+    "Network",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_linux.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_linux.json
index 385158dd6b65d..5c25b47833112 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_linux.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_linux.json
@@ -21,9 +21,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_windows.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_windows.json
index d0a99b32d4713..e86bc96fddae5 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_windows.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_windows.json
@@ -21,9 +21,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_suspicious_login_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_suspicious_login_activity.json
index f309debcdffe9..ae0ac2b716e32 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_suspicious_login_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_suspicious_login_activity.json
@@ -20,9 +20,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Host",
     "Linux",
+    "Threat Detection",
     "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_process.json
index 56874ec371b43..3e35b2af5e3b8 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_process.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_process.json
@@ -17,8 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
   "version": 1
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_user.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_user.json
index f124cda7717c3..7c45ab4dfa08b 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_user.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_user.json
@@ -17,8 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
   "version": 1
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_network_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_network_activity.json
index 0ab591097f975..937fcbc079eb8 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_network_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_network_activity.json
@@ -21,9 +21,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_path_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_path_activity.json
index a7b309e6d7fcd..d45661f737b5d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_path_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_path_activity.json
@@ -20,9 +20,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_all_hosts.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_all_hosts.json
index bc6346f457b65..88764ed1bf46d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_all_hosts.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_all_hosts.json
@@ -21,9 +21,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_creation.json
index 97351a1f517b3..2ebc7ee667d4e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_creation.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_creation.json
@@ -20,9 +20,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_script.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_script.json
index d0dc8d7e40fa2..91714b10d2ab6 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_script.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_script.json
@@ -20,9 +20,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_service.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_service.json
index b7e7a0357e118..3aea73eb489e5 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_service.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_service.json
@@ -20,9 +20,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_user_name.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_user_name.json
index 26bd6837cbde5..749cbb218bcd8 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_user_name.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_user_name.json
@@ -21,9 +21,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_rare_user_runas_event.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_rare_user_runas_event.json
index 1af765f568bb1..8ed8a005d9aa5 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_rare_user_runas_event.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_rare_user_runas_event.json
@@ -20,9 +20,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_rare_user_type10_remote_login.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_rare_user_type10_remote_login.json
index b69e759120ce4..dda4e0bbad88d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_rare_user_type10_remote_login.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_rare_user_type10_remote_login.json
@@ -21,9 +21,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "ML",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "ML"
   ],
   "type": "machine_learning",
-  "version": 2
+  "version": 3
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_mfa_rule.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_mfa_rule.json
index c503d2298adad..0ee0bbd6d6226 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_mfa_rule.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_mfa_rule.json
@@ -24,10 +24,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Identity and Access",
-    "Continuous Monitoring"
+    "Identity and Access"
   ],
   "type": "query",
   "version": 2
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_policy.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_policy.json
index d095d7c1166de..211fdb1ae3474 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_policy.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_policy.json
@@ -24,10 +24,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "type": "query",
   "version": 2
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_mfa_rule.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_mfa_rule.json
index 2fe27575b7b2a..eb726e24c89da 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_mfa_rule.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_mfa_rule.json
@@ -24,10 +24,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Identity and Access",
-    "Continuous Monitoring"
+    "Identity and Access"
   ],
   "type": "query",
   "version": 2
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_network_zone.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_network_zone.json
index 23b3313488847..682dc17f0ed49 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_network_zone.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_network_zone.json
@@ -24,10 +24,11 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Network",
-    "Continuous Monitoring"
+    "Network Security"
   ],
   "type": "query",
   "version": 2
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_policy.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_policy.json
index 5b19031046b66..88e556d37a27c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_policy.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_policy.json
@@ -24,10 +24,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "type": "query",
   "version": 2
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_or_delete_application_sign_on_policy.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_or_delete_application_sign_on_policy.json
index 58ba13e147a38..262a91f8e25c9 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_or_delete_application_sign_on_policy.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_or_delete_application_sign_on_policy.json
@@ -24,10 +24,11 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Identity and Access",
-    "Continuous Monitoring"
+    "Identity and Access"
   ],
   "type": "query",
   "version": 2
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_threat_detected_by_okta_threatinsight.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_threat_detected_by_okta_threatinsight.json
index 1efcf0474c049..0101ae0459454 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_threat_detected_by_okta_threatinsight.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_threat_detected_by_okta_threatinsight.json
@@ -21,10 +21,11 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "type": "query",
   "version": 2
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_administrator_privileges_assigned_to_okta_group.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_administrator_privileges_assigned_to_okta_group.json
index 87d5bf3e0f48c..fad3e3c922478 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_administrator_privileges_assigned_to_okta_group.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_administrator_privileges_assigned_to_okta_group.json
@@ -24,10 +24,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_adobe_hijack_persistence.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_adobe_hijack_persistence.json
index a4c62b98fb060..077147a8ed1a6 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_adobe_hijack_persistence.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_adobe_hijack_persistence.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Persistence"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_app_compat_shim.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_app_compat_shim.json
index e9e2e044ddc04..5c467c39f5128 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_app_compat_shim.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_app_compat_shim.json
@@ -11,13 +11,16 @@
   "language": "eql",
   "license": "Elastic License",
   "name": "Installation of Custom Shim Databases",
-  "query": "/* dependent on wildcard for registry.value */\n\nsequence by process.entity_id with maxspan=5m\n  [process where event.type in (\"start\", \"process_started\") and\n     not (process.name == \"sdbinst.exe\" and process.parent.name == \"msiexec.exe\")]\n  [registry where event.type in (\"creation\", \"change\") and\n     wildcard(registry.path, \"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\AppCompatFlags\\\\Custom\\\\*.sdb\")]\n",
+  "query": "sequence by process.entity_id with maxspan=5m\n  [process where event.type in (\"start\", \"process_started\") and\n     not (process.name : \"sdbinst.exe\" and process.parent.name : \"msiexec.exe\")]\n  [registry where event.type in (\"creation\", \"change\") and\n     wildcard(registry.path, \"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\AppCompatFlags\\\\Custom\\\\*.sdb\")]\n",
   "risk_score": 21,
   "rule_id": "c5ce48a6-7f57-4ee8-9313-3d0024caee10",
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Persistence"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_create_okta_api_token.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_create_okta_api_token.json
index c1d7d51f1401e..9d1a7c7aef464 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_create_okta_api_token.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_create_okta_api_token.json
@@ -24,10 +24,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_deactivate_mfa_for_okta_user_account.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_deactivate_mfa_for_okta_user_account.json
index 9cd9572400a6c..764c60b829498 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_deactivate_mfa_for_okta_user_account.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_deactivate_mfa_for_okta_user_account.json
@@ -24,10 +24,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Identity and Access",
-    "Continuous Monitoring"
+    "Identity and Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_deactivate_okta_policy.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_deactivate_okta_policy.json
index d5c9e505659f6..9003f6877341f 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_deactivate_okta_policy.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_deactivate_okta_policy.json
@@ -24,10 +24,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Monitoring",
-    "Continuous Monitoring"
+    "Monitoring"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_reset_mfa_factors_for_okta_user_account.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_reset_mfa_factors_for_okta_user_account.json
index 302618773e323..4fef3e833a7b6 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_reset_mfa_factors_for_okta_user_account.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_reset_mfa_factors_for_okta_user_account.json
@@ -24,10 +24,11 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Identity",
     "Okta",
+    "Continuous Monitoring",
     "SecOps",
-    "Identity and Access",
-    "Continuous Monitoring"
+    "Identity and Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_account_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_account_created.json
index 645c025ec4738..5c000967ce44d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_account_created.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_account_created.json
@@ -22,11 +22,12 @@
   "rule_id": "df26fd74-1baa-4479-b42e-48da84642330",
   "severity": "low",
   "tags": [
+    "Elastic",
+    "Cloud",
     "Azure",
     "Continuous Monitoring",
-    "Elastic",
-    "Identity and Access",
-    "SecOps"
+    "SecOps",
+    "Identity and Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_runbook_created_or_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_runbook_created_or_modified.json
index e96700e409090..28a5864353942 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_runbook_created_or_modified.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_runbook_created_or_modified.json
@@ -23,6 +23,7 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_webhook_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_webhook_created.json
index f31fdcc18978e..5dde815022283 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_webhook_created.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_webhook_created.json
@@ -23,6 +23,7 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_conditional_access_policy_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_conditional_access_policy_modified.json
similarity index 99%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_conditional_access_policy_modified.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_conditional_access_policy_modified.json
index 8d4d4b971316e..14d6d3d479c6a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_conditional_access_policy_modified.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_conditional_access_policy_modified.json
@@ -20,6 +20,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_pim_user_added_global_admin.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_pim_user_added_global_admin.json
index b8ea2c55dd3f9..24411a40ffc46 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_pim_user_added_global_admin.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_pim_user_added_global_admin.json
@@ -22,6 +22,7 @@
   "severity": "high",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_privileged_identity_management_role_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_privileged_identity_management_role_modified.json
similarity index 99%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_privileged_identity_management_role_modified.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_privileged_identity_management_role_modified.json
index f675a490c4e05..77e955727b2d8 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_privileged_identity_management_role_modified.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_privileged_identity_management_role_modified.json
@@ -21,6 +21,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_network_acl_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_network_acl_creation.json
index 1b98b9744cd5b..8deaa9924cc1d 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_network_acl_creation.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_network_acl_creation.json
@@ -27,11 +27,12 @@
   "rule_id": "39144f38-5284-4f8e-a2ae-e3fd628d90b0",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Network",
-    "Continuous Monitoring"
+    "Network Security"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_service_account_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_service_account_created.json
index aa9d48459262e..62e28e588cd0a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_service_account_created.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_service_account_created.json
@@ -22,6 +22,7 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "GCP",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_gpo_schtask_service_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gpo_schtask_service_creation.json
similarity index 96%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_gpo_schtask_service_creation.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gpo_schtask_service_creation.json
index fbf6fddcb8c00..536eda4e21476 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_gpo_schtask_service_creation.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gpo_schtask_service_creation.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Persistence"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_iam_group_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_iam_group_creation.json
index 0addb86b8d031..963ac46b7ed94 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_iam_group_creation.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_iam_group_creation.json
@@ -25,11 +25,12 @@
   "rule_id": "169f3a93-efc7-4df2-94d6-0d9438c310d1",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Identity and Access",
-    "Continuous Monitoring"
+    "Identity and Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_kernel_module_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_kernel_module_activity.json
index e3dedeef07eb5..b29a8b2384f95 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_kernel_module_activity.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_kernel_module_activity.json
@@ -23,7 +23,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Persistence"
   ],
   "threat": [
     {
@@ -43,5 +46,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_commands.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_commands.json
index 78f035318c614..9e5a6a0eae041 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_commands.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_commands.json
@@ -20,7 +20,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Persistence"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_mfa_disabled_for_azure_user.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_mfa_disabled_for_azure_user.json
similarity index 99%
rename from x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_mfa_disabled_for_azure_user.json
rename to x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_mfa_disabled_for_azure_user.json
index eda6f5b2bdf62..8a9f4d4c661e9 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_mfa_disabled_for_azure_user.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_mfa_disabled_for_azure_user.json
@@ -17,6 +17,7 @@
   "severity": "medium",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_priv_escalation_via_accessibility_features.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_priv_escalation_via_accessibility_features.json
index 5899b58bce4d5..e7f4598a19f33 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_priv_escalation_via_accessibility_features.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_priv_escalation_via_accessibility_features.json
@@ -4,7 +4,8 @@
   ],
   "description": "Windows contains accessibility features that may be launched with a key combination before a user has logged in. An adversary can modify the way these programs are launched to get a command prompt or backdoor without logging in to the system.",
   "index": [
-    "winlogbeat-*"
+    "winlogbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -15,7 +16,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Persistence"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_cluster_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_cluster_creation.json
index eb77c183d90ea..06ca022726aad 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_cluster_creation.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_cluster_creation.json
@@ -27,11 +27,12 @@
   "rule_id": "e14c5fd7-fdd7-49c2-9e5b-ec49d817bc8d",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Asset Visibility",
-    "Continuous Monitoring"
+    "Asset Visibility"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_shell_activity_by_web_server.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_shell_activity_by_web_server.json
index 2aaf0012acabf..ea10fa9bdf865 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_shell_activity_by_web_server.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_shell_activity_by_web_server.json
@@ -23,7 +23,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Persistence"
   ],
   "threat": [
     {
@@ -43,5 +46,5 @@
     }
   ],
   "type": "query",
-  "version": 5
+  "version": 6
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_system_shells_via_services.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_system_shells_via_services.json
index 32d78480325e6..880101e8d9338 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_system_shells_via_services.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_system_shells_via_services.json
@@ -17,7 +17,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Persistence"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_account_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_account_creation.json
index 3f2e00f0976de..9bc603b5ad547 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_account_creation.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_account_creation.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Persistence"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 4
+  "version": 5
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_application.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_application.json
index 8882b87e91291..3fddde78beb33 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_application.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_application.json
@@ -17,6 +17,7 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_service_principal.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_service_principal.json
index f7c0af67692e7..de6482f14d2f0 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_service_principal.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_service_principal.json
@@ -20,6 +20,7 @@
   "severity": "low",
   "tags": [
     "Elastic",
+    "Cloud",
     "Azure",
     "Continuous Monitoring",
     "SecOps",
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_application_shimming.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_application_shimming.json
index f20cc75dfa38b..c9d56a9c68edb 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_application_shimming.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_application_shimming.json
@@ -4,7 +4,8 @@
   ],
   "description": "The Application Shim was created to allow for backward compatibility of software as the operating system codebase changes over time. This Windows functionality has been abused by attackers to stealthily gain persistence and arbitrary code execution in legitimate Windows processes.",
   "index": [
-    "winlogbeat-*"
+    "winlogbeat-*",
+    "logs-endpoint.events.*"
   ],
   "language": "kuery",
   "license": "Elastic License",
@@ -15,7 +16,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Persistence"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_telemetrycontroller_scheduledtask_hijack.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_telemetrycontroller_scheduledtask_hijack.json
index b7f4ec5d8a73c..0622309387f35 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_telemetrycontroller_scheduledtask_hijack.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_telemetrycontroller_scheduledtask_hijack.json
@@ -20,7 +20,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Persistence"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_update_orchestrator_service_hijack.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_update_orchestrator_service_hijack.json
index e512e92a31560..bdddf2eb7e8c7 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_update_orchestrator_service_hijack.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_update_orchestrator_service_hijack.json
@@ -20,7 +20,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Persistence"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_service_suspicious_file.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_service_suspicious_file.json
index 1a76e077a7465..398e4ca22b757 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_service_suspicious_file.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_service_suspicious_file.json
@@ -21,7 +21,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Privilege Escalation"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_suspicious_spl_file.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_suspicious_spl_file.json
index c5ffe5a9f6a11..18da4c8075c8f 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_suspicious_spl_file.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_printspooler_suspicious_spl_file.json
@@ -21,7 +21,10 @@
   "severity": "high",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Privilege Escalation"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_root_login_without_mfa.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_root_login_without_mfa.json
index 16389d43945f1..16af96e98448c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_root_login_without_mfa.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_root_login_without_mfa.json
@@ -24,11 +24,12 @@
   "rule_id": "bc0c6f0d-dab0-47a3-b135-0925f0a333bc",
   "severity": "high",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Identity and Access",
-    "Continuous Monitoring"
+    "Identity and Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_setgid_bit_set_via_chmod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_setgid_bit_set_via_chmod.json
index e72e58132adee..ff63d1e38d950 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_setgid_bit_set_via_chmod.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_setgid_bit_set_via_chmod.json
@@ -18,7 +18,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Privilege Escalation"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_setuid_bit_set_via_chmod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_setuid_bit_set_via_chmod.json
index 5e560097d2545..47490fe08ff12 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_setuid_bit_set_via_chmod.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_setuid_bit_set_via_chmod.json
@@ -18,7 +18,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Privilege Escalation"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sudoers_file_mod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sudoers_file_mod.json
index 73a804fcbda8f..5519f6ce3a9ec 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sudoers_file_mod.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sudoers_file_mod.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Linux"
+    "Host",
+    "Linux",
+    "Threat Detection",
+    "Privilege Escalation"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_uac_bypass_diskcleanup_hijack.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_uac_bypass_diskcleanup_hijack.json
index b22457db49e49..80b01f90d3cf4 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_uac_bypass_diskcleanup_hijack.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_uac_bypass_diskcleanup_hijack.json
@@ -17,7 +17,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Privilege Escalation"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_uac_bypass_event_viewer.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_uac_bypass_event_viewer.json
index 740ff47e5abe5..415111c725828 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_uac_bypass_event_viewer.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_uac_bypass_event_viewer.json
@@ -17,7 +17,10 @@
   "severity": "low",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Privilege Escalation"
   ],
   "threat": [
     {
@@ -37,5 +40,5 @@
     }
   ],
   "type": "query",
-  "version": 3
+  "version": 4
 }
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_uac_sdclt.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_uac_sdclt.json
new file mode 100644
index 0000000000000..ce82db3a96e11
--- /dev/null
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_uac_sdclt.json
@@ -0,0 +1,44 @@
+{
+  "author": [
+    "Elastic"
+  ],
+  "description": "Identifies User Account Control (UAC) bypass via sdclt.exe. Attackers bypass UAC to stealthily execute code with elevated permissions.",
+  "from": "now-9m",
+  "index": [
+    "logs-endpoint.events.*",
+    "winlogbeat-*"
+  ],
+  "language": "eql",
+  "license": "Elastic License",
+  "name": "Bypass UAC via Sdclt",
+  "query": "/* add winlogbeat-* when process.code_signature.* fields are populated */\n\nsequence with maxspan=1m\n  [process where event.type in (\"start\", \"process_started\") and process.name : \"sdclt.exe\" and\n     /* uncomment once in winlogbeat */\n     /* process.code_signature.subject_name == \"Microsoft Corporation\" and process.code_signature.trusted == true and */\n     process.args : \"/kickoffelev\"\n  ] by process.entity_id\n  [process where event.type in (\"start\", \"process_started\") and process.parent.name : \"sdclt.exe\" and\n     not (process.executable : \"C:\\\\Windows\\\\System32\\\\sdclt.exe\" or\n          process.executable : \"C:\\\\Windows\\\\System32\\\\control.exe\" or\n          process.executable : \"C:\\\\Windows\\\\SysWOW64\\\\sdclt.exe\" or\n          process.executable : \"C:\\\\Windows\\\\SysWOW64\\\\control.exe\")\n  ] by process.parent.entity_id\n",
+  "risk_score": 21,
+  "rule_id": "9b54e002-034a-47ac-9307-ad12c03fa900",
+  "severity": "high",
+  "tags": [
+    "Elastic",
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Privilege Escalation"
+  ],
+  "threat": [
+    {
+      "framework": "MITRE ATT&CK",
+      "tactic": {
+        "id": "TA0004",
+        "name": "Privilege Escalation",
+        "reference": "https://attack.mitre.org/tactics/TA0004/"
+      },
+      "technique": [
+        {
+          "id": "T1088",
+          "name": "Bypass User Account Control",
+          "reference": "https://attack.mitre.org/techniques/T1088/"
+        }
+      ]
+    }
+  ],
+  "type": "eql",
+  "version": 1
+}
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_unusual_parentchild_relationship.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_unusual_parentchild_relationship.json
index 0cac8561c7e9c..ad871716a67aa 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_unusual_parentchild_relationship.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_unusual_parentchild_relationship.json
@@ -17,7 +17,10 @@
   "severity": "medium",
   "tags": [
     "Elastic",
-    "Windows"
+    "Host",
+    "Windows",
+    "Threat Detection",
+    "Privilege Escalation"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_updateassumerolepolicy.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_updateassumerolepolicy.json
index 55947e00170ae..3d1e66497bd2e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_updateassumerolepolicy.json
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_updateassumerolepolicy.json
@@ -24,11 +24,12 @@
   "rule_id": "a60326d7-dca7-4fb7-93eb-1ca03a1febbd",
   "severity": "low",
   "tags": [
-    "AWS",
     "Elastic",
+    "Cloud",
+    "AWS",
+    "Continuous Monitoring",
     "SecOps",
-    "Identity and Access",
-    "Continuous Monitoring"
+    "Identity and Access"
   ],
   "threat": [
     {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts
index 8af622e6a128b..fb4763a982f43 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts
@@ -105,7 +105,7 @@ export interface RuleAlertType extends Alert {
 }
 
 // eslint-disable-next-line @typescript-eslint/no-explicit-any
-export interface IRuleStatusAttributes extends Record<string, any> {
+export interface IRuleStatusSOAttributes extends Record<string, any> {
   alertId: string; // created alert id.
   statusDate: StatusDate;
   lastFailureAt: LastFailureAt | null | undefined;
@@ -119,21 +119,35 @@ export interface IRuleStatusAttributes extends Record<string, any> {
   searchAfterTimeDurations: string[] | null | undefined;
 }
 
+export interface IRuleStatusResponseAttributes {
+  alert_id: string; // created alert id.
+  status_date: StatusDate;
+  last_failure_at: LastFailureAt | null | undefined;
+  last_failure_message: LastFailureMessage | null | undefined;
+  last_success_at: LastSuccessAt | null | undefined;
+  last_success_message: LastSuccessMessage | null | undefined;
+  status: JobStatus | null | undefined;
+  last_look_back_date: string | null | undefined;
+  gap: string | null | undefined;
+  bulk_create_time_durations: string[] | null | undefined;
+  search_after_time_durations: string[] | null | undefined;
+}
+
 export interface RuleStatusResponse {
   [key: string]: {
-    current_status: IRuleStatusAttributes | null | undefined;
-    failures: IRuleStatusAttributes[] | null | undefined;
+    current_status: IRuleStatusResponseAttributes | null | undefined;
+    failures: IRuleStatusResponseAttributes[] | null | undefined;
   };
 }
 
 export interface IRuleSavedAttributesSavedObjectAttributes
-  extends IRuleStatusAttributes,
+  extends IRuleStatusSOAttributes,
     SavedObjectAttributes {}
 
 export interface IRuleStatusSavedObject {
   type: string;
   id: string;
-  attributes: Array<SavedObject<IRuleStatusAttributes & SavedObjectAttributes>>;
+  attributes: Array<SavedObject<IRuleStatusSOAttributes & SavedObjectAttributes>>;
   references: unknown[];
   updated_at: string;
   version: string;
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts
index cbf70f3119b31..4559a658c9583 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts
@@ -19,7 +19,7 @@ import {
 } from '../../../../../../../../src/core/server';
 import { loggingSystemMock } from '../../../../../../../../src/core/server/mocks';
 import { RuleTypeParams } from '../../types';
-import { IRuleStatusAttributes } from '../../rules/types';
+import { IRuleStatusSOAttributes } from '../../rules/types';
 import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings';
 import { getListArrayMock } from '../../../../../common/detection_engine/schemas/types/lists.mock';
 import { RulesSchema } from '../../../../../common/detection_engine/schemas/response';
@@ -555,7 +555,7 @@ export const sampleDocSearchResultsWithSortId = (
 export const sampleRuleGuid = '04128c15-0d1b-4716-a4c5-46997ac7f3bd';
 export const sampleIdGuid = 'e1e08ddc-5e37-49ff-a258-5393aa44435a';
 
-export const exampleRuleStatus: () => SavedObject<IRuleStatusAttributes> = () => ({
+export const exampleRuleStatus: () => SavedObject<IRuleStatusSOAttributes> = () => ({
   type: ruleStatusSavedObjectType,
   id: '042e6d90-7069-11ea-af8b-0f8ae4fa817e',
   attributes: {
@@ -577,8 +577,10 @@ export const exampleRuleStatus: () => SavedObject<IRuleStatusAttributes> = () =>
 });
 
 export const exampleFindRuleStatusResponse: (
-  mockStatuses: Array<SavedObject<IRuleStatusAttributes>>
-) => SavedObjectsFindResponse<IRuleStatusAttributes> = (mockStatuses = [exampleRuleStatus()]) => ({
+  mockStatuses: Array<SavedObject<IRuleStatusSOAttributes>>
+) => SavedObjectsFindResponse<IRuleStatusSOAttributes> = (
+  mockStatuses = [exampleRuleStatus()]
+) => ({
   total: 1,
   per_page: 6,
   page: 1,
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_or_create_rule_statuses.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_or_create_rule_statuses.ts
index 913efbe04aa16..1ddec9cd15148 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_or_create_rule_statuses.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_or_create_rule_statuses.ts
@@ -6,7 +6,7 @@
 
 import { SavedObject } from 'src/core/server';
 
-import { IRuleStatusAttributes } from '../rules/types';
+import { IRuleStatusSOAttributes } from '../rules/types';
 import { RuleStatusSavedObjectsClient } from './rule_status_saved_objects_client';
 import { getRuleStatusSavedObjects } from './get_rule_status_saved_objects';
 
@@ -18,7 +18,7 @@ interface RuleStatusParams {
 export const createNewRuleStatus = async ({
   alertId,
   ruleStatusClient,
-}: RuleStatusParams): Promise<SavedObject<IRuleStatusAttributes>> => {
+}: RuleStatusParams): Promise<SavedObject<IRuleStatusSOAttributes>> => {
   const now = new Date().toISOString();
   return ruleStatusClient.create({
     alertId,
@@ -38,7 +38,7 @@ export const createNewRuleStatus = async ({
 export const getOrCreateRuleStatuses = async ({
   alertId,
   ruleStatusClient,
-}: RuleStatusParams): Promise<Array<SavedObject<IRuleStatusAttributes>>> => {
+}: RuleStatusParams): Promise<Array<SavedObject<IRuleStatusSOAttributes>>> => {
   const ruleStatuses = await getRuleStatusSavedObjects({
     alertId,
     ruleStatusClient,
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_rule_status_saved_objects.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_rule_status_saved_objects.ts
index 828b4ea41096e..72a271fb2606f 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_rule_status_saved_objects.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_rule_status_saved_objects.ts
@@ -5,7 +5,7 @@
  */
 
 import { SavedObjectsFindResponse } from 'kibana/server';
-import { IRuleStatusAttributes } from '../rules/types';
+import { IRuleStatusSOAttributes } from '../rules/types';
 import { MAX_RULE_STATUSES } from './rule_status_service';
 import { RuleStatusSavedObjectsClient } from './rule_status_saved_objects_client';
 
@@ -17,7 +17,7 @@ interface GetRuleStatusSavedObject {
 export const getRuleStatusSavedObjects = async ({
   alertId,
   ruleStatusClient,
-}: GetRuleStatusSavedObject): Promise<SavedObjectsFindResponse<IRuleStatusAttributes>> => {
+}: GetRuleStatusSavedObject): Promise<SavedObjectsFindResponse<IRuleStatusSOAttributes>> => {
   return ruleStatusClient.find({
     perPage: MAX_RULE_STATUSES,
     sortField: 'statusDate',
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/rule_status_saved_objects_client.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/rule_status_saved_objects_client.ts
index 4b5faeb5b9d27..f6a08852ac8d5 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/rule_status_saved_objects_client.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/rule_status_saved_objects_client.ts
@@ -12,17 +12,17 @@ import {
   SavedObjectsFindResponse,
 } from '../../../../../../../src/core/server';
 import { ruleStatusSavedObjectType } from '../rules/saved_object_mappings';
-import { IRuleStatusAttributes } from '../rules/types';
+import { IRuleStatusSOAttributes } from '../rules/types';
 
 export interface RuleStatusSavedObjectsClient {
   find: (
     options?: Omit<SavedObjectsFindOptions, 'type'>
-  ) => Promise<SavedObjectsFindResponse<IRuleStatusAttributes>>;
-  create: (attributes: IRuleStatusAttributes) => Promise<SavedObject<IRuleStatusAttributes>>;
+  ) => Promise<SavedObjectsFindResponse<IRuleStatusSOAttributes>>;
+  create: (attributes: IRuleStatusSOAttributes) => Promise<SavedObject<IRuleStatusSOAttributes>>;
   update: (
     id: string,
-    attributes: Partial<IRuleStatusAttributes>
-  ) => Promise<SavedObjectsUpdateResponse<IRuleStatusAttributes>>;
+    attributes: Partial<IRuleStatusSOAttributes>
+  ) => Promise<SavedObjectsUpdateResponse<IRuleStatusSOAttributes>>;
   delete: (id: string) => Promise<{}>;
 }
 
@@ -30,7 +30,10 @@ export const ruleStatusSavedObjectsClientFactory = (
   savedObjectsClient: SavedObjectsClientContract
 ): RuleStatusSavedObjectsClient => ({
   find: (options) =>
-    savedObjectsClient.find<IRuleStatusAttributes>({ ...options, type: ruleStatusSavedObjectType }),
+    savedObjectsClient.find<IRuleStatusSOAttributes>({
+      ...options,
+      type: ruleStatusSavedObjectType,
+    }),
   create: (attributes) => savedObjectsClient.create(ruleStatusSavedObjectType, attributes),
   update: (id, attributes) => savedObjectsClient.update(ruleStatusSavedObjectType, id, attributes),
   delete: (id) => savedObjectsClient.delete(ruleStatusSavedObjectType, id),
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/rule_status_service.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/rule_status_service.ts
index 8fdbe282eece5..433ad4e2affea 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/rule_status_service.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/rule_status_service.ts
@@ -6,7 +6,7 @@
 
 import { assertUnreachable } from '../../../../common/utility_types';
 import { JobStatus } from '../../../../common/detection_engine/schemas/common/schemas';
-import { IRuleStatusAttributes } from '../rules/types';
+import { IRuleStatusSOAttributes } from '../rules/types';
 import { getOrCreateRuleStatuses } from './get_or_create_rule_statuses';
 import { RuleStatusSavedObjectsClient } from './rule_status_saved_objects_client';
 
@@ -30,9 +30,9 @@ export const buildRuleStatusAttributes: (
   status: JobStatus,
   message?: string,
   attributes?: Attributes
-) => Partial<IRuleStatusAttributes> = (status, message, attributes = {}) => {
+) => Partial<IRuleStatusSOAttributes> = (status, message, attributes = {}) => {
   const now = new Date().toISOString();
-  const baseAttributes: Partial<IRuleStatusAttributes> = {
+  const baseAttributes: Partial<IRuleStatusSOAttributes> = {
     ...attributes,
     status,
     statusDate: now,
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts
index 838ac2558b038..bb3a0b4fa6f08 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts
@@ -8,7 +8,6 @@
 
 import { Logger, KibanaRequest } from 'src/core/server';
 
-import { get } from 'lodash';
 import {
   SIGNALS_ID,
   DEFAULT_SEARCH_AFTER_PAGE_SIZE,
@@ -62,6 +61,8 @@ import { buildEqlSearchRequest } from '../../../../common/detection_engine/get_q
 import { bulkInsertSignals } from './single_bulk_create';
 import { buildSignalFromEvent, buildSignalGroupFromSequence } from './build_bulk_body';
 import { createThreatSignals } from './threat_mapping/create_threat_signals';
+import { getIndexVersion } from '../routes/index/get_index_version';
+import { MIN_EQL_RULE_INDEX_VERSION } from '../routes/index/get_signals_template';
 
 export const signalRulesAlertType = ({
   logger,
@@ -119,17 +120,6 @@ export const signalRulesAlertType = ({
         type,
         exceptionsList,
       } = params;
-      const outputIndexTemplateMapping: unknown = await services.callCluster(
-        'indices.getTemplate',
-        { name: outputIndex }
-      );
-      const signalMappingVersion: number | undefined = get(outputIndexTemplateMapping, [
-        outputIndex,
-        'version',
-      ]);
-      if (signalMappingVersion !== undefined && typeof signalMappingVersion !== 'number') {
-        throw new Error('Found non-numeric value for "version" in output index template');
-      }
 
       const searchAfterSize = Math.min(maxSignals, DEFAULT_SEARCH_AFTER_PAGE_SIZE);
       let hasError: boolean = false;
@@ -457,14 +447,24 @@ export const signalRulesAlertType = ({
           if (query === undefined) {
             throw new Error('EQL query rule must have a query defined');
           }
-          const MIN_EQL_RULE_TEMPLATE_VERSION = 2;
-          if (
-            signalMappingVersion === undefined ||
-            signalMappingVersion < MIN_EQL_RULE_TEMPLATE_VERSION
-          ) {
-            throw new Error(
-              `EQL based rules require an update to version ${MIN_EQL_RULE_TEMPLATE_VERSION} of the detection alerts index mapping`
-            );
+          try {
+            const signalIndexVersion = await getIndexVersion(services.callCluster, outputIndex);
+            if (
+              signalIndexVersion === undefined ||
+              signalIndexVersion < MIN_EQL_RULE_INDEX_VERSION
+            ) {
+              throw new Error(
+                `EQL based rules require an update to version ${MIN_EQL_RULE_INDEX_VERSION} of the detection alerts index mapping`
+              );
+            }
+          } catch (err) {
+            if (err.statusCode === 403) {
+              throw new Error(
+                `EQL based rules require the user that created it to have the view_index_metadata, read, and write permissions for index: ${outputIndex}`
+              );
+            } else {
+              throw err;
+            }
           }
           const inputIndex = await getInputIndex(services, version, index);
           const request = buildEqlSearchRequest(
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.test.ts
index 7b7c40f0c4355..c4869f024a977 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.test.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.test.ts
@@ -105,7 +105,9 @@ describe('singleSearchAfter', () => {
       timestampOverride: undefined,
       buildRuleMessage,
     });
-    expect(searchErrors).toEqual(['reason: some reason, type: some type, caused by: some reason']);
+    expect(searchErrors).toEqual([
+      'reason: "some reason" type: "some type" caused by reason: "some reason" caused by type: "some type"',
+    ]);
   });
   test('if singleSearchAfter works with a given sort id', async () => {
     const searchAfterSortId = '1234567891111';
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts
index 157f741439bd2..894e934ff0247 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts
@@ -878,7 +878,7 @@ describe('utils', () => {
       ];
       const createdErrors = createErrorsFromShard({ errors });
       expect(createdErrors).toEqual([
-        'reason: some reason, type: some type, caused by: some reason',
+        'reason: "some reason" type: "some type" caused by reason: "some reason" caused by type: "some type"',
       ]);
     });
 
@@ -917,8 +917,54 @@ describe('utils', () => {
       ];
       const createdErrors = createErrorsFromShard({ errors });
       expect(createdErrors).toEqual([
-        'reason: some reason, type: some type, caused by: some reason',
-        'reason: some reason 2, type: some type 2, caused by: some reason 2',
+        'reason: "some reason" type: "some type" caused by reason: "some reason" caused by type: "some type"',
+        'reason: "some reason 2" type: "some type 2" caused by reason: "some reason 2" caused by type: "some type 2"',
+      ]);
+    });
+
+    test('You can have missing values for the shard errors and get the expected output of an empty string', () => {
+      const errors: ShardError[] = [
+        {
+          shard: 1,
+          index: 'index-123',
+          node: 'node-123',
+          reason: {},
+        },
+      ];
+      const createdErrors = createErrorsFromShard({ errors });
+      expect(createdErrors).toEqual(['']);
+    });
+
+    test('You can have a single value for the shard errors and get expected output without extra spaces anywhere', () => {
+      const errors: ShardError[] = [
+        {
+          shard: 1,
+          index: 'index-123',
+          node: 'node-123',
+          reason: {
+            reason: 'some reason something went wrong',
+          },
+        },
+      ];
+      const createdErrors = createErrorsFromShard({ errors });
+      expect(createdErrors).toEqual(['reason: "some reason something went wrong"']);
+    });
+
+    test('You can have two values for the shard errors and get expected output with one space exactly between the two values', () => {
+      const errors: ShardError[] = [
+        {
+          shard: 1,
+          index: 'index-123',
+          node: 'node-123',
+          reason: {
+            reason: 'some reason something went wrong',
+            caused_by: { type: 'some type' },
+          },
+        },
+      ];
+      const createdErrors = createErrorsFromShard({ errors });
+      expect(createdErrors).toEqual([
+        'reason: "some reason something went wrong" caused by type: "some type"',
       ]);
     });
   });
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts
index ac10f5ed9a72d..e2b39b8d0a8c8 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts
@@ -511,7 +511,23 @@ export const getSignalTimeTuples = ({
  */
 export const createErrorsFromShard = ({ errors }: { errors: ShardError[] }): string[] => {
   return errors.map((error) => {
-    return `reason: ${error.reason.reason}, type: ${error.reason.caused_by.type}, caused by: ${error.reason.caused_by.reason}`;
+    const {
+      reason: {
+        reason,
+        type,
+        caused_by: { reason: causedByReason, type: causedByType } = {
+          reason: undefined,
+          type: undefined,
+        },
+      } = {},
+    } = error;
+
+    return [
+      ...(reason != null ? [`reason: "${reason}"`] : []),
+      ...(type != null ? [`type: "${type}"`] : []),
+      ...(causedByReason != null ? [`caused by reason: "${causedByReason}"`] : []),
+      ...(causedByType != null ? [`caused by type: "${causedByType}"`] : []),
+    ].join(' ');
   });
 };
 
diff --git a/x-pack/plugins/security_solution/server/lib/framework/kibana_framework_adapter.ts b/x-pack/plugins/security_solution/server/lib/framework/kibana_framework_adapter.ts
index 6d9e9b13bc356..e36fb1144e93f 100644
--- a/x-pack/plugins/security_solution/server/lib/framework/kibana_framework_adapter.ts
+++ b/x-pack/plugins/security_solution/server/lib/framework/kibana_framework_adapter.ts
@@ -149,14 +149,7 @@ export class KibanaBackendFrameworkAdapter implements FrameworkAdapter {
   }
 
   public getIndexPatternsService(request: FrameworkRequest): FrameworkIndexPatternsService {
-    // eslint-disable-next-line @typescript-eslint/no-explicit-any
-    const callCluster = async (endpoint: string, params?: Record<string, any>) =>
-      this.callWithRequest(request, endpoint, {
-        ...params,
-        allowNoIndices: true,
-      });
-
-    return new IndexPatternsFetcher(callCluster);
+    return new IndexPatternsFetcher(request.context.core.elasticsearch.client.asCurrentUser, true);
   }
 }
 
diff --git a/x-pack/plugins/security_solution/server/lib/types.ts b/x-pack/plugins/security_solution/server/lib/types.ts
index 29db38bbbea68..c735412aedbf5 100644
--- a/x-pack/plugins/security_solution/server/lib/types.ts
+++ b/x-pack/plugins/security_solution/server/lib/types.ts
@@ -48,21 +48,26 @@ export interface ShardsResponse {
   failures?: ShardError[];
 }
 
-export interface ShardError {
+/**
+ * This type is being very conservative with the partials to not expect anything to
+ * be guaranteed on the type as we don't have regular and proper types of ShardError.
+ * Once we do, remove this type for the regular ShardError type from the elastic library.
+ */
+export type ShardError = Partial<{
   shard: number;
   index: string;
   node: string;
-  reason: {
+  reason: Partial<{
     type: string;
     reason: string;
     index_uuid: string;
     index: string;
-    caused_by: {
+    caused_by: Partial<{
       type: string;
       reason: string;
-    };
-  };
-}
+    }>;
+  }>;
+}>;
 
 export interface SearchResponse<T> {
   took: number;
diff --git a/x-pack/plugins/security_solution/server/search_strategy/index_fields/index.ts b/x-pack/plugins/security_solution/server/search_strategy/index_fields/index.ts
index bc461f3885a70..aef092949a47e 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/index_fields/index.ts
+++ b/x-pack/plugins/security_solution/server/search_strategy/index_fields/index.ts
@@ -30,9 +30,7 @@ export const securitySolutionIndexFieldsProvider = (): ISearchStrategy<
       from(
         new Promise<IndexFieldsStrategyResponse>(async (resolve) => {
           const { elasticsearch } = context.core;
-          const indexPatternsFetcher = new IndexPatternsFetcher(
-            elasticsearch.legacy.client.callAsCurrentUser
-          );
+          const indexPatternsFetcher = new IndexPatternsFetcher(elasticsearch.client.asCurrentUser);
           const dedupeIndices = dedupeIndexName(request.indices);
 
           const responsesIndexFields = await Promise.all(
diff --git a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts
index 7cdbd8b11bb06..8a94ae4ed82f5 100644
--- a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts
+++ b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts
@@ -5,21 +5,12 @@
  */
 
 import _ from 'lodash';
-import {
-  asUpdateByQuery,
-  shouldBeOneOf,
-  mustBeAllOf,
-  ExistsFilter,
-  TermFilter,
-  RangeFilter,
-} from './query_clauses';
+import { asUpdateByQuery, shouldBeOneOf, mustBeAllOf } from './query_clauses';
 
 import {
-  updateFields,
+  updateFieldsAndMarkAsFailed,
   IdleTaskWithExpiredRunAt,
   RunningOrClaimingTaskWithExpiredRetryAt,
-  TaskWithSchedule,
-  taskWithLessThanMaxAttempts,
   SortByRunAtAndRetryAt,
 } from './mark_available_tasks_as_claimed';
 
@@ -40,29 +31,29 @@ describe('mark_available_tasks_as_claimed', () => {
         createTaskRunner: () => ({ run: () => Promise.resolve() }),
       },
     });
+    const claimTasksById = undefined;
     const defaultMaxAttempts = 1;
     const taskManagerId = '3478fg6-82374f6-83467gf5-384g6f';
     const claimOwnershipUntil = '2019-02-12T21:01:22.479Z';
+    const fieldUpdates = {
+      ownerId: taskManagerId,
+      retryAt: claimOwnershipUntil,
+    };
 
     expect(
       asUpdateByQuery({
         query: mustBeAllOf(
           // Either a task with idle status and runAt <= now or
           // status running or claiming with a retryAt <= now.
-          shouldBeOneOf(IdleTaskWithExpiredRunAt, RunningOrClaimingTaskWithExpiredRetryAt),
-          // Either task has an schedule or the attempts < the maximum configured
-          shouldBeOneOf<ExistsFilter | TermFilter | RangeFilter>(
-            TaskWithSchedule,
-            ...Array.from(definitions).map(([type, { maxAttempts }]) =>
-              taskWithLessThanMaxAttempts(type, maxAttempts || defaultMaxAttempts)
-            )
-          )
+          shouldBeOneOf(IdleTaskWithExpiredRunAt, RunningOrClaimingTaskWithExpiredRetryAt)
+        ),
+        update: updateFieldsAndMarkAsFailed(
+          fieldUpdates,
+          claimTasksById || [],
+          Array.from(definitions).reduce((accumulator, [type, { maxAttempts }]) => {
+            return { ...accumulator, [type]: maxAttempts || defaultMaxAttempts };
+          }, {})
         ),
-        update: updateFields({
-          ownerId: taskManagerId,
-          status: 'claiming',
-          retryAt: claimOwnershipUntil,
-        }),
         sort: SortByRunAtAndRetryAt,
       })
     ).toEqual({
@@ -100,42 +91,6 @@ describe('mark_available_tasks_as_claimed', () => {
                 ],
               },
             },
-            // Either task has an recurring schedule or the attempts < the maximum configured
-            {
-              bool: {
-                should: [
-                  { exists: { field: 'task.schedule' } },
-                  {
-                    bool: {
-                      must: [
-                        { term: { 'task.taskType': 'sampleTask' } },
-                        {
-                          range: {
-                            'task.attempts': {
-                              lt: 5,
-                            },
-                          },
-                        },
-                      ],
-                    },
-                  },
-                  {
-                    bool: {
-                      must: [
-                        { term: { 'task.taskType': 'otherTask' } },
-                        {
-                          range: {
-                            'task.attempts': {
-                              lt: 1,
-                            },
-                          },
-                        },
-                      ],
-                    },
-                  },
-                ],
-              },
-            },
           ],
         },
       },
@@ -158,12 +113,26 @@ if (doc['task.runAt'].size()!=0) {
       },
       seq_no_primary_term: true,
       script: {
-        source: `ctx._source.task.ownerId=params.ownerId; ctx._source.task.status=params.status; ctx._source.task.retryAt=params.retryAt;`,
+        source: `
+  if (ctx._source.task.schedule != null || ctx._source.task.attempts < params.taskMaxAttempts[ctx._source.task.taskType] || params.claimTasksById.contains(ctx._id)) {
+    ctx._source.task.status = "claiming"; ${Object.keys(fieldUpdates)
+      .map((field) => `ctx._source.task.${field}=params.fieldUpdates.${field};`)
+      .join(' ')}
+  } else {
+    ctx._source.task.status = "failed";
+  }
+  `,
         lang: 'painless',
         params: {
-          ownerId: taskManagerId,
-          retryAt: claimOwnershipUntil,
-          status: 'claiming',
+          fieldUpdates: {
+            ownerId: taskManagerId,
+            retryAt: claimOwnershipUntil,
+          },
+          claimTasksById: [],
+          taskMaxAttempts: {
+            sampleTask: 5,
+            otherTask: 1,
+          },
         },
       },
     });
diff --git a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts
index 699af3ed07d5d..072ec4648201a 100644
--- a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts
+++ b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts
@@ -100,12 +100,26 @@ if (doc['task.runAt'].size()!=0) {
   },
 };
 
-export const updateFields = (fieldUpdates: {
-  [field: string]: string | number | Date;
-}): ScriptClause => ({
-  source: Object.keys(fieldUpdates)
-    .map((field) => `ctx._source.task.${field}=params.${field};`)
-    .join(' '),
+export const updateFieldsAndMarkAsFailed = (
+  fieldUpdates: {
+    [field: string]: string | number | Date;
+  },
+  claimTasksById: string[],
+  taskMaxAttempts: { [field: string]: number }
+): ScriptClause => ({
+  source: `
+  if (ctx._source.task.schedule != null || ctx._source.task.attempts < params.taskMaxAttempts[ctx._source.task.taskType] || params.claimTasksById.contains(ctx._id)) {
+    ctx._source.task.status = "claiming"; ${Object.keys(fieldUpdates)
+      .map((field) => `ctx._source.task.${field}=params.fieldUpdates.${field};`)
+      .join(' ')}
+  } else {
+    ctx._source.task.status = "failed";
+  }
+  `,
   lang: 'painless',
-  params: fieldUpdates,
+  params: {
+    fieldUpdates,
+    claimTasksById,
+    taskMaxAttempts,
+  },
 });
diff --git a/x-pack/plugins/task_manager/server/queries/query_clauses.ts b/x-pack/plugins/task_manager/server/queries/query_clauses.ts
index f16ee302d6c83..5503b9cd94105 100644
--- a/x-pack/plugins/task_manager/server/queries/query_clauses.ts
+++ b/x-pack/plugins/task_manager/server/queries/query_clauses.ts
@@ -165,7 +165,12 @@ export interface ScriptClause {
   source: string;
   lang: string;
   params: {
-    [field: string]: string | number | Date;
+    [field: string]:
+      | string
+      | number
+      | Date
+      | string[]
+      | { [field: string]: string | number | Date };
   };
 }
 
diff --git a/x-pack/plugins/task_manager/server/task_store.test.ts b/x-pack/plugins/task_manager/server/task_store.test.ts
index a40df3b84132e..46e55df4ee1e6 100644
--- a/x-pack/plugins/task_manager/server/task_store.test.ts
+++ b/x-pack/plugins/task_manager/server/task_store.test.ts
@@ -415,41 +415,6 @@ describe('TaskStore', () => {
                             ],
                           },
                         },
-                        {
-                          bool: {
-                            should: [
-                              { exists: { field: 'task.schedule' } },
-                              {
-                                bool: {
-                                  must: [
-                                    { term: { 'task.taskType': 'foo' } },
-                                    {
-                                      range: {
-                                        'task.attempts': {
-                                          lt: maxAttempts,
-                                        },
-                                      },
-                                    },
-                                  ],
-                                },
-                              },
-                              {
-                                bool: {
-                                  must: [
-                                    { term: { 'task.taskType': 'bar' } },
-                                    {
-                                      range: {
-                                        'task.attempts': {
-                                          lt: customMaxAttempts,
-                                        },
-                                      },
-                                    },
-                                  ],
-                                },
-                              },
-                            ],
-                          },
-                        },
                       ],
                     },
                   },
@@ -501,6 +466,11 @@ if (doc['task.runAt'].size()!=0) {
       const maxAttempts = _.random(2, 43);
       const customMaxAttempts = _.random(44, 100);
       const definitions = new TaskTypeDictionary(mockLogger());
+      const taskManagerId = uuid.v1();
+      const fieldUpdates = {
+        ownerId: taskManagerId,
+        retryAt: new Date(Date.now()),
+      };
       definitions.registerTaskDefinitions({
         foo: {
           title: 'foo',
@@ -514,10 +484,11 @@ if (doc['task.runAt'].size()!=0) {
       });
       const {
         args: {
-          updateByQuery: { body: { query, sort } = {} },
+          updateByQuery: { body: { query, script, sort } = {} },
         },
       } = await testClaimAvailableTasks({
         opts: {
+          taskManagerId,
           maxAttempts,
           definitions,
         },
@@ -576,41 +547,6 @@ if (doc['task.runAt'].size()!=0) {
                                 ],
                               },
                             },
-                            {
-                              bool: {
-                                should: [
-                                  { exists: { field: 'task.schedule' } },
-                                  {
-                                    bool: {
-                                      must: [
-                                        { term: { 'task.taskType': 'foo' } },
-                                        {
-                                          range: {
-                                            'task.attempts': {
-                                              lt: maxAttempts,
-                                            },
-                                          },
-                                        },
-                                      ],
-                                    },
-                                  },
-                                  {
-                                    bool: {
-                                      must: [
-                                        { term: { 'task.taskType': 'bar' } },
-                                        {
-                                          range: {
-                                            'task.attempts': {
-                                              lt: customMaxAttempts,
-                                            },
-                                          },
-                                        },
-                                      ],
-                                    },
-                                  },
-                                ],
-                              },
-                            },
                           ],
                         },
                       },
@@ -640,6 +576,30 @@ if (doc['task.runAt'].size()!=0) {
         },
       });
 
+      expect(script).toMatchObject({
+        source: `
+  if (ctx._source.task.schedule != null || ctx._source.task.attempts < params.taskMaxAttempts[ctx._source.task.taskType] || params.claimTasksById.contains(ctx._id)) {
+    ctx._source.task.status = "claiming"; ${Object.keys(fieldUpdates)
+      .map((field) => `ctx._source.task.${field}=params.fieldUpdates.${field};`)
+      .join(' ')}
+  } else {
+    ctx._source.task.status = "failed";
+  }
+  `,
+        lang: 'painless',
+        params: {
+          fieldUpdates,
+          claimTasksById: [
+            'task:33c6977a-ed6d-43bd-98d9-3f827f7b7cd8',
+            'task:a208b22c-14ec-4fb4-995f-d2ff7a3b03b8',
+          ],
+          taskMaxAttempts: {
+            bar: customMaxAttempts,
+            foo: maxAttempts,
+          },
+        },
+      });
+
       expect(sort).toMatchObject([
         '_score',
         {
@@ -665,6 +625,10 @@ if (doc['task.runAt'].size()!=0) {
     test('it claims tasks by setting their ownerId, status and retryAt', async () => {
       const taskManagerId = uuid.v1();
       const claimOwnershipUntil = new Date(Date.now());
+      const fieldUpdates = {
+        ownerId: taskManagerId,
+        retryAt: claimOwnershipUntil,
+      };
       const {
         args: {
           updateByQuery: { body: { script } = {} },
@@ -679,12 +643,24 @@ if (doc['task.runAt'].size()!=0) {
         },
       });
       expect(script).toMatchObject({
-        source: `ctx._source.task.ownerId=params.ownerId; ctx._source.task.status=params.status; ctx._source.task.retryAt=params.retryAt;`,
+        source: `
+  if (ctx._source.task.schedule != null || ctx._source.task.attempts < params.taskMaxAttempts[ctx._source.task.taskType] || params.claimTasksById.contains(ctx._id)) {
+    ctx._source.task.status = "claiming"; ${Object.keys(fieldUpdates)
+      .map((field) => `ctx._source.task.${field}=params.fieldUpdates.${field};`)
+      .join(' ')}
+  } else {
+    ctx._source.task.status = "failed";
+  }
+  `,
         lang: 'painless',
         params: {
-          ownerId: taskManagerId,
-          retryAt: claimOwnershipUntil,
-          status: 'claiming',
+          fieldUpdates,
+          claimTasksById: [],
+          taskMaxAttempts: {
+            dernstraight: 2,
+            report: 2,
+            yawn: 2,
+          },
         },
       });
     });
diff --git a/x-pack/plugins/task_manager/server/task_store.ts b/x-pack/plugins/task_manager/server/task_store.ts
index 63b6ab7412ec5..1d49fbc2ecc7b 100644
--- a/x-pack/plugins/task_manager/server/task_store.ts
+++ b/x-pack/plugins/task_manager/server/task_store.ts
@@ -41,21 +41,16 @@ import {
   shouldBeOneOf,
   mustBeAllOf,
   filterDownBy,
-  ExistsFilter,
-  TermFilter,
-  RangeFilter,
   asPinnedQuery,
   matchesClauses,
   SortOptions,
 } from './queries/query_clauses';
 
 import {
-  updateFields,
+  updateFieldsAndMarkAsFailed,
   IdleTaskWithExpiredRunAt,
   InactiveTasks,
   RunningOrClaimingTaskWithExpiredRetryAt,
-  TaskWithSchedule,
-  taskWithLessThanMaxAttempts,
   SortByRunAtAndRetryAt,
   tasksClaimedByOwner,
 } from './queries/mark_available_tasks_as_claimed';
@@ -259,18 +254,13 @@ export class TaskStore {
     claimTasksById: OwnershipClaimingOpts['claimTasksById'],
     size: OwnershipClaimingOpts['size']
   ): Promise<number> {
-    const tasksWithRemainingAttempts = [...this.definitions].map(([type, { maxAttempts }]) =>
-      taskWithLessThanMaxAttempts(type, maxAttempts || this.maxAttempts)
-    );
+    const taskMaxAttempts = [...this.definitions].reduce((accumulator, [type, { maxAttempts }]) => {
+      return { ...accumulator, [type]: maxAttempts || this.maxAttempts };
+    }, {});
     const queryForScheduledTasks = mustBeAllOf(
       // Either a task with idle status and runAt <= now or
       // status running or claiming with a retryAt <= now.
-      shouldBeOneOf(IdleTaskWithExpiredRunAt, RunningOrClaimingTaskWithExpiredRetryAt),
-      // Either task has a schedule or the attempts < the maximum configured
-      shouldBeOneOf<ExistsFilter | TermFilter | RangeFilter>(
-        TaskWithSchedule,
-        ...tasksWithRemainingAttempts
-      )
+      shouldBeOneOf(IdleTaskWithExpiredRunAt, RunningOrClaimingTaskWithExpiredRetryAt)
     );
 
     // The documents should be sorted by runAt/retryAt, unless there are pinned
@@ -295,11 +285,14 @@ export class TaskStore {
           ),
           filterDownBy(InactiveTasks)
         ),
-        update: updateFields({
-          ownerId: this.taskManagerId,
-          status: 'claiming',
-          retryAt: claimOwnershipUntil,
-        }),
+        update: updateFieldsAndMarkAsFailed(
+          {
+            ownerId: this.taskManagerId,
+            retryAt: claimOwnershipUntil,
+          },
+          claimTasksById || [],
+          taskMaxAttempts
+        ),
         sort,
       }),
       {
diff --git a/x-pack/plugins/telemetry_collection_xpack/tsconfig.json b/x-pack/plugins/telemetry_collection_xpack/tsconfig.json
new file mode 100644
index 0000000000000..476f5926f757a
--- /dev/null
+++ b/x-pack/plugins/telemetry_collection_xpack/tsconfig.json
@@ -0,0 +1,21 @@
+{
+  "extends": "../../../tsconfig.base.json",
+  "compilerOptions": {
+    "composite": true,
+    "outDir": "./target/types",
+    "emitDeclarationOnly": true,
+    "declaration": true,
+    "declarationMap": true
+  },
+  "include": [
+    "common/**/*",
+    "server/**/*",
+    "../../../typings/*"
+  ],
+  "references": [
+    { "path": "../../../src/core/tsconfig.json" },
+    { "path": "../../../src/plugins/telemetry_collection_manager/tsconfig.json" },
+    { "path": "../../../src/plugins/telemetry/tsconfig.json" }
+  ]
+}
+
diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx
index 8f19db6fc827d..404f9aeec7c68 100644
--- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx
+++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx
@@ -102,11 +102,6 @@ export const StepDefineForm: FC<StepDefineFormProps> = React.memo((props) => {
     toastNotifications,
   };
 
-  // TODO This should use the actual value of `indices.query.bool.max_clause_count`
-  const maxIndexFields = 1024;
-  const numIndexFields = indexPattern.fields.length;
-  const disabledQuery = numIndexFields > maxIndexFields;
-
   const copyToClipboardSource = getIndexDevConsoleStatement(pivotQuery, indexPattern.title);
   const copyToClipboardSourceDescription = i18n.translate(
     'xpack.transform.indexPreview.copyClipboardTooltip',
@@ -181,18 +176,6 @@ export const StepDefineForm: FC<StepDefineFormProps> = React.memo((props) => {
             label={i18n.translate('xpack.transform.stepDefineForm.indexPatternLabel', {
               defaultMessage: 'Index pattern',
             })}
-            helpText={
-              disabledQuery
-                ? i18n.translate('xpack.transform.stepDefineForm.indexPatternHelpText', {
-                    defaultMessage:
-                      'An optional query for this index pattern is not supported. The number of supported index fields is {maxIndexFields} whereas this index has {numIndexFields} fields.',
-                    values: {
-                      maxIndexFields,
-                      numIndexFields,
-                    },
-                  })
-                : ''
-            }
           >
             <span>{indexPattern.title}</span>
           </EuiFormRow>
@@ -214,7 +197,7 @@ export const StepDefineForm: FC<StepDefineFormProps> = React.memo((props) => {
                 {/* Flex Column #1: Search Bar / Advanced Search Editor */}
                 {searchItems.savedSearch === undefined && (
                   <>
-                    {!disabledQuery && !isAdvancedSourceEditorEnabled && (
+                    {!isAdvancedSourceEditorEnabled && (
                       <SourceSearchBar
                         indexPattern={indexPattern}
                         searchBar={stepDefineForm.searchBar}
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 5cabdd62d7c87..d5142175befc8 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -8570,9 +8570,6 @@
     "xpack.indexLifecycleMgmt.editPolicy.lifecyclePoliciesLoadingFailedTitle": "既存のライフサイクルポリシーを読み込めません",
     "xpack.indexLifecycleMgmt.editPolicy.lifecyclePoliciesReloadButton": "再試行",
     "xpack.indexLifecycleMgmt.editPolicy.lifecyclePolicyDescriptionText": "インデックスへのアクティブな書き込みから削除までの、インデックスライフサイクルの 4 つのフェーズを自動化するには、インデックスポリシーを使用します。",
-    "xpack.indexLifecycleMgmt.editPolicy.maximumAgeMissingError": "最高年齢が必要です。",
-    "xpack.indexLifecycleMgmt.editPolicy.maximumDocumentsMissingError": "最高ドキュメント数が必要です。",
-    "xpack.indexLifecycleMgmt.editPolicy.maximumIndexSizeMissingError": "最大インデックスサイズが必要です。",
     "xpack.indexLifecycleMgmt.editPolicy.nameLabel": "名前",
     "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.customOption.description": "ノード属性を使用して、シャード割り当てを制御します。{learnMoreLink}。",
     "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.doNotModifyAllocationOption": "割り当て構成を修正しない",
@@ -19764,7 +19761,6 @@
     "xpack.transform.stepDefineForm.groupByExistsErrorMessage": "「{aggName}」という名前のグループ分け構成は既に存在します。",
     "xpack.transform.stepDefineForm.groupByLabel": "グループ分けの条件",
     "xpack.transform.stepDefineForm.groupByPlaceholder": "グループ分けの条件フィールドを追加…",
-    "xpack.transform.stepDefineForm.indexPatternHelpText": "このインデックスパターンのオプションのクエリはサポートされていません。サポートされているインデックスフィールドの数は {maxIndexFields} で、このインデックスには {numIndexFields} 個のフィールドがあります。",
     "xpack.transform.stepDefineForm.indexPatternLabel": "インデックスパターン",
     "xpack.transform.stepDefineForm.invalidKuerySyntaxErrorMessageQueryBar": "無効なクエリ:{errorMessage}",
     "xpack.transform.stepDefineForm.maxSubAggsLevelsLimitMessage": "フォームで追加できる下位集約の最大レベル数に達しました。別のレベルを追加する場合は、JSON構成を編集してください。",
@@ -20272,7 +20268,6 @@
     "xpack.triggersActionsUI.sections.addModalConnectorForm.saveButtonLabel": "保存",
     "xpack.triggersActionsUI.sections.addModalConnectorForm.updateSuccessNotificationText": "「{connectorName}」を作成しました",
     "xpack.triggersActionsUI.sections.alertAdd.betaBadgeTooltipContent": "{pluginName} はベータ段階で、変更される可能性があります。デザインとコードはオフィシャル GA 機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャル GA 機能の SLA が適用されません。",
-    "xpack.triggersActionsUI.sections.alertAdd.cancelButtonLabel": "キャンセル",
     "xpack.triggersActionsUI.sections.alertAdd.conditionPrompt": "条件を定義してください",
     "xpack.triggersActionsUI.sections.alertAdd.errorLoadingAlertVisualizationTitle": "アラートビジュアライゼーションを読み込めません",
     "xpack.triggersActionsUI.sections.alertAdd.flyoutTitle": "アラートの作成",
@@ -20280,7 +20275,6 @@
     "xpack.triggersActionsUI.sections.alertAdd.loadingAlertVisualizationDescription": "アラートビジュアライゼーションを読み込み中...",
     "xpack.triggersActionsUI.sections.alertAdd.operationName": "作成",
     "xpack.triggersActionsUI.sections.alertAdd.previewAlertVisualizationDescription": "プレビューを生成するための式を完成します。",
-    "xpack.triggersActionsUI.sections.alertAdd.saveButtonLabel": "保存",
     "xpack.triggersActionsUI.sections.alertAdd.saveErrorNotificationText": "アラートを作成できません。",
     "xpack.triggersActionsUI.sections.alertAdd.saveSuccessNotificationText": "「{alertName}」 を保存しました",
     "xpack.triggersActionsUI.sections.alertAdd.selectIndex": "インデックスを選択してください",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 229938a3c1d08..f04f9e17017c1 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -8577,9 +8577,6 @@
     "xpack.indexLifecycleMgmt.editPolicy.lifecyclePoliciesLoadingFailedTitle": "无法加载现有生命周期策略",
     "xpack.indexLifecycleMgmt.editPolicy.lifecyclePoliciesReloadButton": "重试",
     "xpack.indexLifecycleMgmt.editPolicy.lifecyclePolicyDescriptionText": "使用索引策略自动化索引生命周期的四个阶段,从频繁地写入到索引到删除索引。",
-    "xpack.indexLifecycleMgmt.editPolicy.maximumAgeMissingError": "最大存在时间必填。",
-    "xpack.indexLifecycleMgmt.editPolicy.maximumDocumentsMissingError": "最大文档数必填。",
-    "xpack.indexLifecycleMgmt.editPolicy.maximumIndexSizeMissingError": "最大索引大小必填。",
     "xpack.indexLifecycleMgmt.editPolicy.nameLabel": "名称",
     "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.customOption.description": "使用节点属性控制分片分配。{learnMoreLink}。",
     "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.doNotModifyAllocationOption": "不要修改分配配置",
@@ -19783,7 +19780,6 @@
     "xpack.transform.stepDefineForm.groupByExistsErrorMessage": "名称为“{aggName}”的分组依据配置已存在。",
     "xpack.transform.stepDefineForm.groupByLabel": "分组依据",
     "xpack.transform.stepDefineForm.groupByPlaceholder": "添加分组依据字段……",
-    "xpack.transform.stepDefineForm.indexPatternHelpText": "不支持此索引模式的可选查询。受支持索引字段数目为 {maxIndexFields},而此索引有 {numIndexFields} 个字段。",
     "xpack.transform.stepDefineForm.indexPatternLabel": "索引模式",
     "xpack.transform.stepDefineForm.invalidKuerySyntaxErrorMessageQueryBar": "查询无效:{errorMessage}",
     "xpack.transform.stepDefineForm.maxSubAggsLevelsLimitMessage": "您已达到可在表单中添加的最大子聚合级别数。如果想再添加一个级别,请编辑 JSON 配置。",
@@ -20292,7 +20288,6 @@
     "xpack.triggersActionsUI.sections.addModalConnectorForm.saveButtonLabel": "保存",
     "xpack.triggersActionsUI.sections.addModalConnectorForm.updateSuccessNotificationText": "已创建“{connectorName}”",
     "xpack.triggersActionsUI.sections.alertAdd.betaBadgeTooltipContent": "{pluginName} 为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束。",
-    "xpack.triggersActionsUI.sections.alertAdd.cancelButtonLabel": "取消",
     "xpack.triggersActionsUI.sections.alertAdd.conditionPrompt": "定义条件",
     "xpack.triggersActionsUI.sections.alertAdd.errorLoadingAlertVisualizationTitle": "无法加载告警可视化",
     "xpack.triggersActionsUI.sections.alertAdd.flyoutTitle": "创建告警",
@@ -20300,7 +20295,6 @@
     "xpack.triggersActionsUI.sections.alertAdd.loadingAlertVisualizationDescription": "正在加载告警可视化……",
     "xpack.triggersActionsUI.sections.alertAdd.operationName": "创建",
     "xpack.triggersActionsUI.sections.alertAdd.previewAlertVisualizationDescription": "完成表达式以生成预览。",
-    "xpack.triggersActionsUI.sections.alertAdd.saveButtonLabel": "保存",
     "xpack.triggersActionsUI.sections.alertAdd.saveErrorNotificationText": "无法创建告警。",
     "xpack.triggersActionsUI.sections.alertAdd.saveSuccessNotificationText": "已保存“{alertName}”",
     "xpack.triggersActionsUI.sections.alertAdd.selectIndex": "选择索引",
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/boot.tsx b/x-pack/plugins/triggers_actions_ui/public/application/boot.tsx
index c157f923e4447..80f9ac532d1c9 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/boot.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/boot.tsx
@@ -28,5 +28,7 @@ export const boot = (bootDeps: BootDeps) => {
     </I18nContext>,
     element
   );
-  return () => unmountComponentAtNode(element);
+  return () => {
+    unmountComponentAtNode(element);
+  };
 };
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.test.tsx
index 1d908920db8b0..a7de73c9aab29 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.test.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.test.tsx
@@ -10,6 +10,7 @@ import { HealthCheck } from './health_check';
 
 import { act } from 'react-dom/test-utils';
 import { httpServiceMock } from '../../../../../../src/core/public/mocks';
+import { HealthContextProvider } from '../context/health_context';
 
 const docLinks = { ELASTIC_WEBSITE_URL: 'elastic.co/', DOC_LINK_VERSION: 'current' };
 
@@ -20,9 +21,11 @@ describe('health check', () => {
     http.get.mockImplementationOnce(() => new Promise(() => {}));
 
     const { queryByText, container } = render(
-      <HealthCheck http={http} docLinks={docLinks}>
-        <p>{'shouldnt render'}</p>
-      </HealthCheck>
+      <HealthContextProvider>
+        <HealthCheck http={http} docLinks={docLinks} waitForCheck={true}>
+          <p>{'shouldnt render'}</p>
+        </HealthCheck>
+      </HealthContextProvider>
     );
     await act(async () => {
       // wait for useEffect to run
@@ -32,13 +35,33 @@ describe('health check', () => {
     expect(queryByText('shouldnt render')).not.toBeInTheDocument();
   });
 
+  it('renders children immediately if waitForCheck is false', async () => {
+    http.get.mockImplementationOnce(() => new Promise(() => {}));
+
+    const { queryByText, container } = render(
+      <HealthContextProvider>
+        <HealthCheck http={http} docLinks={docLinks} waitForCheck={false}>
+          <p>{'should render'}</p>
+        </HealthCheck>
+      </HealthContextProvider>
+    );
+    await act(async () => {
+      // wait for useEffect to run
+    });
+
+    expect(container.getElementsByClassName('euiLoadingSpinner').length).toBe(0);
+    expect(queryByText('should render')).toBeInTheDocument();
+  });
+
   it('renders children if keys are enabled', async () => {
     http.get.mockResolvedValue({ isSufficientlySecure: true, hasPermanentEncryptionKey: true });
 
     const { queryByText } = render(
-      <HealthCheck http={http} docLinks={docLinks}>
-        <p>{'should render'}</p>
-      </HealthCheck>
+      <HealthContextProvider>
+        <HealthCheck http={http} docLinks={docLinks} waitForCheck={true}>
+          <p>{'should render'}</p>
+        </HealthCheck>
+      </HealthContextProvider>
     );
     await act(async () => {
       // wait for useEffect to run
@@ -53,9 +76,11 @@ describe('health check', () => {
     }));
 
     const { queryAllByText } = render(
-      <HealthCheck http={http} docLinks={docLinks}>
-        <p>{'should render'}</p>
-      </HealthCheck>
+      <HealthContextProvider>
+        <HealthCheck http={http} docLinks={docLinks} waitForCheck={true}>
+          <p>{'should render'}</p>
+        </HealthCheck>
+      </HealthContextProvider>
     );
     await act(async () => {
       // wait for useEffect to run
@@ -81,9 +106,11 @@ describe('health check', () => {
     }));
 
     const { queryByText, queryByRole } = render(
-      <HealthCheck http={http} docLinks={docLinks}>
-        <p>{'should render'}</p>
-      </HealthCheck>
+      <HealthContextProvider>
+        <HealthCheck http={http} docLinks={docLinks} waitForCheck={true}>
+          <p>{'should render'}</p>
+        </HealthCheck>
+      </HealthContextProvider>
     );
     await act(async () => {
       // wait for useEffect to run
@@ -108,9 +135,11 @@ describe('health check', () => {
     }));
 
     const { queryByText } = render(
-      <HealthCheck http={http} docLinks={docLinks}>
-        <p>{'should render'}</p>
-      </HealthCheck>
+      <HealthContextProvider>
+        <HealthCheck http={http} docLinks={docLinks} waitForCheck={true}>
+          <p>{'should render'}</p>
+        </HealthCheck>
+      </HealthContextProvider>
     );
     await act(async () => {
       // wait for useEffect to run
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.tsx
index 009f582424765..c4d0b4976266e 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.tsx
@@ -18,33 +18,39 @@ import { EuiEmptyPrompt, EuiCode } from '@elastic/eui';
 import { AlertingFrameworkHealth } from '../../types';
 import { health } from '../lib/alert_api';
 import './health_check.scss';
+import { useHealthContext } from '../context/health_context';
 
 interface Props {
   docLinks: Pick<DocLinksStart, 'ELASTIC_WEBSITE_URL' | 'DOC_LINK_VERSION'>;
   http: HttpSetup;
   inFlyout?: boolean;
+  waitForCheck: boolean;
 }
 
 export const HealthCheck: React.FunctionComponent<Props> = ({
   docLinks,
   http,
   children,
+  waitForCheck,
   inFlyout = false,
 }) => {
+  const { setLoadingHealthCheck } = useHealthContext();
   const [alertingHealth, setAlertingHealth] = React.useState<Option<AlertingFrameworkHealth>>(none);
 
   React.useEffect(() => {
     (async function () {
+      setLoadingHealthCheck(true);
       setAlertingHealth(some(await health({ http })));
+      setLoadingHealthCheck(false);
     })();
-  }, [http]);
+  }, [http, setLoadingHealthCheck]);
 
   const className = inFlyout ? 'alertingFlyoutHealthCheck' : 'alertingHealthCheck';
 
   return pipe(
     alertingHealth,
     fold(
-      () => <EuiLoadingSpinner size="m" />,
+      () => (waitForCheck ? <EuiLoadingSpinner size="m" /> : <Fragment>{children}</Fragment>),
       (healthCheck) => {
         return healthCheck?.isSufficientlySecure && healthCheck?.hasPermanentEncryptionKey ? (
           <Fragment>{children}</Fragment>
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/context/health_context.tsx b/x-pack/plugins/triggers_actions_ui/public/application/context/health_context.tsx
new file mode 100644
index 0000000000000..de27f6db761e8
--- /dev/null
+++ b/x-pack/plugins/triggers_actions_ui/public/application/context/health_context.tsx
@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { createContext, useCallback, useContext, useMemo, useState } from 'react';
+
+export interface HealthContextValue {
+  loadingHealthCheck: boolean;
+  setLoadingHealthCheck: (loading: boolean) => void;
+}
+
+const defaultHealthContext: HealthContextValue = {
+  loadingHealthCheck: false,
+  setLoadingHealthCheck: (loading: boolean) => {
+    throw new Error(
+      'setLoadingHealthCheck was not initialized, set it when you invoke the context'
+    );
+  },
+};
+
+const HealthContext = createContext<HealthContextValue>(defaultHealthContext);
+
+export const HealthContextProvider = ({ children }: { children: React.ReactNode }) => {
+  const [loading, setLoading] = useState<boolean>(false);
+
+  const setLoadingHealthCheck = useCallback((isLoading: boolean) => {
+    setLoading(isLoading);
+  }, []);
+
+  const value = useMemo(() => {
+    return { loadingHealthCheck: loading, setLoadingHealthCheck };
+  }, [loading, setLoadingHealthCheck]);
+
+  return <HealthContext.Provider value={value}>{children}</HealthContext.Provider>;
+};
+
+export const useHealthContext = () => {
+  const ctx = useContext(HealthContext);
+  if (!ctx) {
+    throw new Error('HealthContext has not been set.');
+  }
+  return ctx;
+};
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/home.tsx b/x-pack/plugins/triggers_actions_ui/public/application/home.tsx
index eb6b1ada3ba93..f009a04d40978 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/home.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/home.tsx
@@ -31,6 +31,7 @@ import { ActionsConnectorsList } from './sections/actions_connectors_list/compon
 import { AlertsList } from './sections/alerts_list/components/alerts_list';
 import { PLUGIN } from './constants/plugin';
 import { HealthCheck } from './components/health_check';
+import { HealthContextProvider } from './context/health_context';
 
 interface MatchParams {
   section: Section;
@@ -139,9 +140,11 @@ export const TriggersActionsUIHome: React.FunctionComponent<RouteComponentProps<
               exact
               path={routeToConnectors}
               component={() => (
-                <HealthCheck docLinks={docLinks} http={http}>
-                  <ActionsConnectorsList />
-                </HealthCheck>
+                <HealthContextProvider>
+                  <HealthCheck docLinks={docLinks} http={http} waitForCheck={true}>
+                    <ActionsConnectorsList />
+                  </HealthCheck>
+                </HealthContextProvider>
               )}
             />
           )}
@@ -149,9 +152,11 @@ export const TriggersActionsUIHome: React.FunctionComponent<RouteComponentProps<
             exact
             path={routeToAlerts}
             component={() => (
-              <HealthCheck docLinks={docLinks} http={http}>
-                <AlertsList />
-              </HealthCheck>
+              <HealthContextProvider>
+                <HealthCheck docLinks={docLinks} http={http} inFlyout={true} waitForCheck={true}>
+                  <AlertsList />
+                </HealthCheck>
+              </HealthContextProvider>
             )}
           />
         </Switch>
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.tsx
index 7be7e60c2e19c..763462ba6ebf4 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.tsx
@@ -10,11 +10,6 @@ import {
   EuiTitle,
   EuiFlyoutHeader,
   EuiFlyout,
-  EuiFlyoutFooter,
-  EuiFlexGroup,
-  EuiFlexItem,
-  EuiButtonEmpty,
-  EuiButton,
   EuiFlyoutBody,
   EuiPortal,
   EuiBetaBadge,
@@ -29,6 +24,8 @@ import { HealthCheck } from '../../components/health_check';
 import { PLUGIN } from '../../constants/plugin';
 import { ConfirmAlertSave } from './confirm_alert_save';
 import { hasShowActionsCapability } from '../../lib/capabilities';
+import AlertAddFooter from './alert_add_footer';
+import { HealthContextProvider } from '../../context/health_context';
 
 interface AlertAddProps {
   consumer: string;
@@ -183,54 +180,37 @@ export const AlertAdd = ({
             </h3>
           </EuiTitle>
         </EuiFlyoutHeader>
-        <HealthCheck docLinks={docLinks} http={http} inFlyout={true}>
-          <EuiFlyoutBody>
-            <AlertForm
-              alert={alert}
-              dispatch={dispatch}
-              errors={errors}
-              canChangeTrigger={canChangeTrigger}
-              operation={i18n.translate('xpack.triggersActionsUI.sections.alertAdd.operationName', {
-                defaultMessage: 'create',
-              })}
+        <HealthContextProvider>
+          <HealthCheck docLinks={docLinks} http={http} inFlyout={true} waitForCheck={false}>
+            <EuiFlyoutBody>
+              <AlertForm
+                alert={alert}
+                dispatch={dispatch}
+                errors={errors}
+                canChangeTrigger={canChangeTrigger}
+                operation={i18n.translate(
+                  'xpack.triggersActionsUI.sections.alertAdd.operationName',
+                  {
+                    defaultMessage: 'create',
+                  }
+                )}
+              />
+            </EuiFlyoutBody>
+            <AlertAddFooter
+              isSaving={isSaving}
+              hasErrors={hasErrors || hasActionErrors}
+              onSave={async () => {
+                setIsSaving(true);
+                if (shouldConfirmSave) {
+                  setIsConfirmAlertSaveModalOpen(true);
+                } else {
+                  await saveAlertAndCloseFlyout();
+                }
+              }}
+              onCancel={closeFlyout}
             />
-          </EuiFlyoutBody>
-          <EuiFlyoutFooter>
-            <EuiFlexGroup justifyContent="spaceBetween">
-              <EuiFlexItem grow={false}>
-                <EuiButtonEmpty data-test-subj="cancelSaveAlertButton" onClick={closeFlyout}>
-                  {i18n.translate('xpack.triggersActionsUI.sections.alertAdd.cancelButtonLabel', {
-                    defaultMessage: 'Cancel',
-                  })}
-                </EuiButtonEmpty>
-              </EuiFlexItem>
-              <EuiFlexItem grow={false}>
-                <EuiButton
-                  fill
-                  color="secondary"
-                  data-test-subj="saveAlertButton"
-                  type="submit"
-                  iconType="check"
-                  isDisabled={hasErrors || hasActionErrors}
-                  isLoading={isSaving}
-                  onClick={async () => {
-                    setIsSaving(true);
-                    if (shouldConfirmSave) {
-                      setIsConfirmAlertSaveModalOpen(true);
-                    } else {
-                      await saveAlertAndCloseFlyout();
-                    }
-                  }}
-                >
-                  <FormattedMessage
-                    id="xpack.triggersActionsUI.sections.alertAdd.saveButtonLabel"
-                    defaultMessage="Save"
-                  />
-                </EuiButton>
-              </EuiFlexItem>
-            </EuiFlexGroup>
-          </EuiFlyoutFooter>
-        </HealthCheck>
+          </HealthCheck>
+        </HealthContextProvider>
         {isConfirmAlertSaveModalOpen && (
           <ConfirmAlertSave
             onConfirm={async () => {
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add_footer.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add_footer.tsx
new file mode 100644
index 0000000000000..92e1198de8440
--- /dev/null
+++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add_footer.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;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React from 'react';
+import { FormattedMessage } from '@kbn/i18n/react';
+import {
+  EuiFlyoutFooter,
+  EuiFlexGroup,
+  EuiFlexItem,
+  EuiButtonEmpty,
+  EuiButton,
+} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { useHealthContext } from '../../context/health_context';
+
+interface AlertAddFooterProps {
+  isSaving: boolean;
+  hasErrors: boolean;
+  onSave: () => void;
+  onCancel: () => void;
+}
+
+export const AlertAddFooter = ({ isSaving, hasErrors, onSave, onCancel }: AlertAddFooterProps) => {
+  const { loadingHealthCheck } = useHealthContext();
+
+  return (
+    <EuiFlyoutFooter>
+      <EuiFlexGroup justifyContent="spaceBetween">
+        <EuiFlexItem grow={false}>
+          <EuiButtonEmpty data-test-subj="cancelSaveAlertButton" onClick={onCancel}>
+            {i18n.translate('xpack.triggersActionsUI.sections.alertAddFooter.cancelButtonLabel', {
+              defaultMessage: 'Cancel',
+            })}
+          </EuiButtonEmpty>
+        </EuiFlexItem>
+        <EuiFlexItem grow={false}>
+          <EuiButton
+            fill
+            color="secondary"
+            data-test-subj="saveAlertButton"
+            type="submit"
+            iconType="check"
+            isDisabled={hasErrors || loadingHealthCheck}
+            isLoading={isSaving}
+            onClick={onSave}
+          >
+            <FormattedMessage
+              id="xpack.triggersActionsUI.sections.alertAddFooter.saveButtonLabel"
+              defaultMessage="Save"
+            />
+          </EuiButton>
+        </EuiFlexItem>
+      </EuiFlexGroup>
+    </EuiFlyoutFooter>
+  );
+};
+
+// eslint-disable-next-line import/no-default-export
+export { AlertAddFooter as default };
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.tsx
index b60aa04ee9f27..0435a4cc33cb8 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.tsx
@@ -28,6 +28,7 @@ import { alertReducer } from './alert_reducer';
 import { updateAlert } from '../../lib/alert_api';
 import { HealthCheck } from '../../components/health_check';
 import { PLUGIN } from '../../constants/plugin';
+import { HealthContextProvider } from '../../context/health_context';
 
 interface AlertEditProps {
   initialAlert: Alert;
@@ -135,74 +136,82 @@ export const AlertEdit = ({ initialAlert, onClose }: AlertEditProps) => {
             </h3>
           </EuiTitle>
         </EuiFlyoutHeader>
-        <HealthCheck docLinks={docLinks} http={http} inFlyout={true}>
-          <EuiFlyoutBody>
-            {hasActionsDisabled && (
-              <Fragment>
-                <EuiCallOut
-                  size="s"
-                  color="danger"
-                  iconType="alert"
-                  data-test-subj="hasActionsDisabled"
-                  title={i18n.translate(
-                    'xpack.triggersActionsUI.sections.alertEdit.disabledActionsWarningTitle',
-                    { defaultMessage: 'This alert has actions that are disabled' }
-                  )}
-                />
-                <EuiSpacer />
-              </Fragment>
-            )}
-            <AlertForm
-              alert={alert}
-              dispatch={dispatch}
-              errors={errors}
-              canChangeTrigger={false}
-              setHasActionsDisabled={setHasActionsDisabled}
-              setHasActionsWithBrokenConnector={setHasActionsWithBrokenConnector}
-              operation="i18n.translate('xpack.triggersActionsUI.sections.alertEdit.operationName', {
-                defaultMessage: 'edit',
-              })"
-            />
-          </EuiFlyoutBody>
-          <EuiFlyoutFooter>
-            <EuiFlexGroup justifyContent="spaceBetween">
-              <EuiFlexItem grow={false}>
-                <EuiButtonEmpty data-test-subj="cancelSaveEditedAlertButton" onClick={closeFlyout}>
-                  {i18n.translate('xpack.triggersActionsUI.sections.alertEdit.cancelButtonLabel', {
-                    defaultMessage: 'Cancel',
-                  })}
-                </EuiButtonEmpty>
-              </EuiFlexItem>
-              <EuiFlexItem grow={false}>
-                <EuiButton
-                  fill
-                  color="secondary"
-                  data-test-subj="saveEditedAlertButton"
-                  type="submit"
-                  iconType="check"
-                  isDisabled={hasErrors || hasActionErrors || hasActionsWithBrokenConnector}
-                  isLoading={isSaving}
-                  onClick={async () => {
-                    setIsSaving(true);
-                    const savedAlert = await onSaveAlert();
-                    setIsSaving(false);
-                    if (savedAlert) {
-                      closeFlyout();
-                      if (reloadAlerts) {
-                        reloadAlerts();
-                      }
-                    }
-                  }}
-                >
-                  <FormattedMessage
-                    id="xpack.triggersActionsUI.sections.alertEdit.saveButtonLabel"
-                    defaultMessage="Save"
+        <HealthContextProvider>
+          <HealthCheck docLinks={docLinks} http={http} inFlyout={true} waitForCheck={true}>
+            <EuiFlyoutBody>
+              {hasActionsDisabled && (
+                <Fragment>
+                  <EuiCallOut
+                    size="s"
+                    color="danger"
+                    iconType="alert"
+                    data-test-subj="hasActionsDisabled"
+                    title={i18n.translate(
+                      'xpack.triggersActionsUI.sections.alertEdit.disabledActionsWarningTitle',
+                      { defaultMessage: 'This alert has actions that are disabled' }
+                    )}
                   />
-                </EuiButton>
-              </EuiFlexItem>
-            </EuiFlexGroup>
-          </EuiFlyoutFooter>
-        </HealthCheck>
+                  <EuiSpacer />
+                </Fragment>
+              )}
+              <AlertForm
+                alert={alert}
+                dispatch={dispatch}
+                errors={errors}
+                canChangeTrigger={false}
+                setHasActionsDisabled={setHasActionsDisabled}
+                setHasActionsWithBrokenConnector={setHasActionsWithBrokenConnector}
+                operation="i18n.translate('xpack.triggersActionsUI.sections.alertEdit.operationName', {
+                  defaultMessage: 'edit',
+                })"
+              />
+            </EuiFlyoutBody>
+            <EuiFlyoutFooter>
+              <EuiFlexGroup justifyContent="spaceBetween">
+                <EuiFlexItem grow={false}>
+                  <EuiButtonEmpty
+                    data-test-subj="cancelSaveEditedAlertButton"
+                    onClick={closeFlyout}
+                  >
+                    {i18n.translate(
+                      'xpack.triggersActionsUI.sections.alertEdit.cancelButtonLabel',
+                      {
+                        defaultMessage: 'Cancel',
+                      }
+                    )}
+                  </EuiButtonEmpty>
+                </EuiFlexItem>
+                <EuiFlexItem grow={false}>
+                  <EuiButton
+                    fill
+                    color="secondary"
+                    data-test-subj="saveEditedAlertButton"
+                    type="submit"
+                    iconType="check"
+                    isDisabled={hasErrors || hasActionErrors || hasActionsWithBrokenConnector}
+                    isLoading={isSaving}
+                    onClick={async () => {
+                      setIsSaving(true);
+                      const savedAlert = await onSaveAlert();
+                      setIsSaving(false);
+                      if (savedAlert) {
+                        closeFlyout();
+                        if (reloadAlerts) {
+                          reloadAlerts();
+                        }
+                      }
+                    }}
+                  >
+                    <FormattedMessage
+                      id="xpack.triggersActionsUI.sections.alertEdit.saveButtonLabel"
+                      defaultMessage="Save"
+                    />
+                  </EuiButton>
+                </EuiFlexItem>
+              </EuiFlexGroup>
+            </EuiFlyoutFooter>
+          </HealthCheck>
+        </HealthContextProvider>
       </EuiFlyout>
     </EuiPortal>
   );
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.tsx
index 8800f149c033b..d2ca0abe566ad 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.tsx
@@ -105,9 +105,7 @@ export const AlertForm = ({
   } = alertsContext;
   const canShowActions = hasShowActionsCapability(capabilities);
 
-  const [alertTypeModel, setAlertTypeModel] = useState<AlertTypeModel | null>(
-    alert.alertTypeId ? alertTypeRegistry.get(alert.alertTypeId) : null
-  );
+  const [alertTypeModel, setAlertTypeModel] = useState<AlertTypeModel | null>(null);
 
   const [alertTypesIndex, setAlertTypesIndex] = useState<AlertTypeIndex | undefined>(undefined);
   const [alertInterval, setAlertInterval] = useState<number | undefined>(
@@ -149,6 +147,10 @@ export const AlertForm = ({
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, []);
 
+  useEffect(() => {
+    setAlertTypeModel(alert.alertTypeId ? alertTypeRegistry.get(alert.alertTypeId) : null);
+  }, [alert, alertTypeRegistry]);
+
   const setAlertProperty = (key: string, value: any) => {
     dispatch({ command: { type: 'setProperty' }, payload: { key, value } });
   };
diff --git a/x-pack/plugins/triggers_actions_ui/public/plugin.ts b/x-pack/plugins/triggers_actions_ui/public/plugin.ts
index ef585eca1d67c..874a380f56b5f 100644
--- a/x-pack/plugins/triggers_actions_ui/public/plugin.ts
+++ b/x-pack/plugins/triggers_actions_ui/public/plugin.ts
@@ -5,10 +5,10 @@
  */
 
 import {
-  CoreStart,
   CoreSetup,
-  PluginInitializerContext,
+  CoreStart,
   Plugin as CorePlugin,
+  PluginInitializerContext,
 } from 'src/core/public';
 
 import { i18n } from '@kbn/i18n';
@@ -17,10 +17,9 @@ import { registerBuiltInAlertTypes } from './application/components/builtin_aler
 import { ActionTypeModel, AlertTypeModel } from './types';
 import { TypeRegistry } from './application/type_registry';
 import {
-  ManagementSetup,
   ManagementAppMountParams,
+  ManagementSetup,
 } from '../../../../src/plugins/management/public';
-import { boot } from './application/boot';
 import { ChartsPluginStart } from '../../../../src/plugins/charts/public';
 import { PluginStartContract as AlertingStart } from '../../alerts/public';
 import { DataPublicPluginStart } from '../../../../src/plugins/data/public';
@@ -63,11 +62,9 @@ export class Plugin
   private initializerContext: PluginInitializerContext;
 
   constructor(initializerContext: PluginInitializerContext) {
-    const actionTypeRegistry = new TypeRegistry<ActionTypeModel>();
-    this.actionTypeRegistry = actionTypeRegistry;
+    this.actionTypeRegistry = new TypeRegistry<ActionTypeModel>();
 
-    const alertTypeRegistry = new TypeRegistry<AlertTypeModel>();
-    this.alertTypeRegistry = alertTypeRegistry;
+    this.alertTypeRegistry = new TypeRegistry<AlertTypeModel>();
 
     this.initializerContext = initializerContext;
   }
@@ -88,7 +85,10 @@ export class Plugin
           PluginsStart,
           unknown
         ];
-        boot({
+
+        const { boot } = await import('./application/boot');
+
+        return boot({
           dataPlugin: pluginsStart.data,
           charts: pluginsStart.charts,
           alerts: pluginsStart.alerts,
@@ -107,7 +107,6 @@ export class Plugin
           actionTypeRegistry,
           alertTypeRegistry,
         });
-        return () => {};
       },
     });
 
diff --git a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts
index 3fc26811d46eb..7feb916046e3a 100644
--- a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts
+++ b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts
@@ -7,6 +7,7 @@
 import { schema } from '@kbn/config-schema';
 import { i18n } from '@kbn/i18n';
 import Mustache from 'mustache';
+import { ElasticsearchClient } from 'kibana/server';
 import { UptimeAlertTypeFactory } from './types';
 import { esKuery } from '../../../../../../src/plugins/data/server';
 import { JsonObject } from '../../../../../../src/plugins/kibana_utils/common';
@@ -81,6 +82,7 @@ export const generateFilterDSL = async (
 export const formatFilterString = async (
   dynamicSettings: DynamicSettings,
   callES: ESAPICaller,
+  esClient: ElasticsearchClient,
   filters: StatusCheckFilters,
   search: string,
   libs?: UMServerLibs
@@ -88,9 +90,10 @@ export const formatFilterString = async (
   await generateFilterDSL(
     () =>
       libs?.requests?.getIndexPattern
-        ? libs?.requests?.getIndexPattern({ callES, dynamicSettings })
+        ? libs?.requests?.getIndexPattern({ callES, esClient, dynamicSettings })
         : getUptimeIndexPattern({
             callES,
+            esClient,
             dynamicSettings,
           }),
     filters,
@@ -237,6 +240,7 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = (_server, libs) =
     async executor(
       { params: rawParams, state, services: { alertInstanceFactory } },
       callES,
+      esClient,
       dynamicSettings
     ) {
       const {
@@ -252,7 +256,14 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = (_server, libs) =
         timerange: oldVersionTimeRange,
       } = rawParams;
 
-      const filterString = await formatFilterString(dynamicSettings, callES, filters, search, libs);
+      const filterString = await formatFilterString(
+        dynamicSettings,
+        callES,
+        esClient,
+        filters,
+        search,
+        libs
+      );
 
       const timerange = oldVersionTimeRange || {
         from: isAutoGenerated
diff --git a/x-pack/plugins/uptime/server/lib/alerts/uptime_alert_wrapper.ts b/x-pack/plugins/uptime/server/lib/alerts/uptime_alert_wrapper.ts
index b8a56405ca160..390b6d347996c 100644
--- a/x-pack/plugins/uptime/server/lib/alerts/uptime_alert_wrapper.ts
+++ b/x-pack/plugins/uptime/server/lib/alerts/uptime_alert_wrapper.ts
@@ -4,7 +4,7 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-import { ILegacyScopedClusterClient } from 'kibana/server';
+import { ILegacyScopedClusterClient, ElasticsearchClient } from 'kibana/server';
 import { AlertExecutorOptions, AlertType, AlertTypeState } from '../../../../alerts/server';
 import { savedObjectsAdapter } from '../saved_objects';
 import { DynamicSettings } from '../../../common/runtime_types';
@@ -13,6 +13,7 @@ export interface UptimeAlertType extends Omit<AlertType, 'executor' | 'producer'
   executor: (
     options: AlertExecutorOptions,
     callES: ILegacyScopedClusterClient['callAsCurrentUser'],
+    esClient: ElasticsearchClient,
     dynamicSettings: DynamicSettings
   ) => Promise<AlertTypeState | void>;
 }
@@ -22,13 +23,13 @@ export const uptimeAlertWrapper = (uptimeAlert: UptimeAlertType) => ({
   producer: 'uptime',
   executor: async (options: AlertExecutorOptions) => {
     const {
-      services: { callCluster: callES },
+      services: { callCluster: callES, scopedClusterClient },
     } = options;
 
     const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings(
       options.services.savedObjectsClient
     );
 
-    return uptimeAlert.executor(options, callES, dynamicSettings);
+    return uptimeAlert.executor(options, callES, scopedClusterClient, dynamicSettings);
   },
 });
diff --git a/x-pack/plugins/uptime/server/lib/requests/get_index_pattern.ts b/x-pack/plugins/uptime/server/lib/requests/get_index_pattern.ts
index 1d284143a1ab0..06846a73ed3d7 100644
--- a/x-pack/plugins/uptime/server/lib/requests/get_index_pattern.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/get_index_pattern.ts
@@ -4,7 +4,7 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
-import { LegacyAPICaller, LegacyCallAPIOptions } from 'src/core/server';
+import { ElasticsearchClient } from 'kibana/server';
 import { UMElasticsearchQueryFn } from '../adapters';
 import { IndexPatternsFetcher, FieldDescriptor } from '../../../../../../src/plugins/data/server';
 
@@ -14,15 +14,10 @@ export interface IndexPatternTitleAndFields {
 }
 
 export const getUptimeIndexPattern: UMElasticsearchQueryFn<
-  {},
+  { esClient: ElasticsearchClient },
   IndexPatternTitleAndFields | undefined
-> = async ({ callES, dynamicSettings }) => {
-  const callAsCurrentUser: LegacyAPICaller = async (
-    endpoint: string,
-    clientParams: Record<string, any> = {},
-    options?: LegacyCallAPIOptions
-  ) => callES(endpoint, clientParams, options);
-  const indexPatternsFetcher = new IndexPatternsFetcher(callAsCurrentUser);
+> = async ({ esClient, dynamicSettings }) => {
+  const indexPatternsFetcher = new IndexPatternsFetcher(esClient);
 
   // Since `getDynamicIndexPattern` is called in setup_request (and thus by every endpoint)
   // and since `getFieldsForWildcard` will throw if the specified indices don't exist,
diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts
index fbcbc37ae0cc2..ec750f92656b2 100644
--- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts
@@ -4,6 +4,7 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
+import { ElasticsearchClient } from 'kibana/server';
 import { ESAPICaller, UMElasticsearchQueryFn } from '../adapters';
 import { MonitorDetails, MonitorError } from '../../../common/runtime_types';
 import { formatFilterString } from '../alerts/status_check';
@@ -13,10 +14,12 @@ export interface GetMonitorDetailsParams {
   dateStart: string;
   dateEnd: string;
   alertsClient: any;
+  esClient: ElasticsearchClient;
 }
 
 const getMonitorAlerts = async (
   callES: ESAPICaller,
+  esClient: ElasticsearchClient,
   dynamicSettings: any,
   alertsClient: any,
   monitorId: string
@@ -67,6 +70,7 @@ const getMonitorAlerts = async (
     const parsedFilters = await formatFilterString(
       dynamicSettings,
       callES,
+      esClient,
       currAlert.params.filters,
       currAlert.params.search
     );
@@ -84,7 +88,7 @@ const getMonitorAlerts = async (
 export const getMonitorDetails: UMElasticsearchQueryFn<
   GetMonitorDetailsParams,
   MonitorDetails
-> = async ({ callES, dynamicSettings, monitorId, dateStart, dateEnd, alertsClient }) => {
+> = async ({ callES, esClient, dynamicSettings, monitorId, dateStart, dateEnd, alertsClient }) => {
   const queryFilters: any = [
     {
       range: {
@@ -134,7 +138,13 @@ export const getMonitorDetails: UMElasticsearchQueryFn<
 
   const monitorError: MonitorError | undefined = data?.error;
   const errorTimestamp: string | undefined = data?.['@timestamp'];
-  const monAlerts = await getMonitorAlerts(callES, dynamicSettings, alertsClient, monitorId);
+  const monAlerts = await getMonitorAlerts(
+    callES,
+    esClient,
+    dynamicSettings,
+    alertsClient,
+    monitorId
+  );
   return {
     monitorId,
     error: monitorError,
diff --git a/x-pack/plugins/uptime/server/rest_api/index_state/get_index_pattern.ts b/x-pack/plugins/uptime/server/rest_api/index_state/get_index_pattern.ts
index 26715f0ff37b6..baf999158a29e 100644
--- a/x-pack/plugins/uptime/server/rest_api/index_state/get_index_pattern.ts
+++ b/x-pack/plugins/uptime/server/rest_api/index_state/get_index_pattern.ts
@@ -16,7 +16,11 @@ export const createGetIndexPatternRoute: UMRestApiRouteFactory = (libs: UMServer
     try {
       return response.ok({
         body: {
-          ...(await libs.requests.getIndexPattern({ callES, dynamicSettings })),
+          ...(await libs.requests.getIndexPattern({
+            callES,
+            esClient: _context.core.elasticsearch.client.asCurrentUser,
+            dynamicSettings,
+          })),
         },
       });
     } catch (e) {
diff --git a/x-pack/plugins/uptime/server/rest_api/monitors/monitors_details.ts b/x-pack/plugins/uptime/server/rest_api/monitors/monitors_details.ts
index bb54effc0d57e..8bbb4fcb5575c 100644
--- a/x-pack/plugins/uptime/server/rest_api/monitors/monitors_details.ts
+++ b/x-pack/plugins/uptime/server/rest_api/monitors/monitors_details.ts
@@ -28,6 +28,7 @@ export const createGetMonitorDetailsRoute: UMRestApiRouteFactory = (libs: UMServ
       body: {
         ...(await libs.requests.getMonitorDetails({
           callES,
+          esClient: context.core.elasticsearch.client.asCurrentUser,
           dynamicSettings,
           monitorId,
           dateStart,
diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/migrations.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/migrations.ts
index 1dd88832e38b7..5992bb54c81fd 100644
--- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/migrations.ts
+++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/migrations.ts
@@ -30,24 +30,29 @@ export default function createGetTests({ getService }: FtrProviderContext) {
       expect(response.status).to.eql(200);
       expect(response.body.config).key('incidentConfiguration');
       expect(response.body.config).not.key('casesConfiguration');
-      expect(response.body.config.incidentConfiguration).to.eql({
-        mapping: [
-          {
-            actionType: 'overwrite',
-            source: 'title',
-            target: 'summary',
-          },
-          {
-            actionType: 'overwrite',
-            source: 'description',
-            target: 'description',
-          },
-          {
-            actionType: 'append',
-            source: 'comments',
-            target: 'comments',
-          },
-        ],
+      expect(response.body.config).to.eql({
+        apiUrl:
+          'http://elastic:changeme@localhost:5620/api/_actions-FTS-external-service-simulators/jira',
+        incidentConfiguration: {
+          mapping: [
+            {
+              actionType: 'overwrite',
+              source: 'title',
+              target: 'summary',
+            },
+            {
+              actionType: 'overwrite',
+              source: 'description',
+              target: 'description',
+            },
+            {
+              actionType: 'append',
+              source: 'comments',
+              target: 'comments',
+            },
+          ],
+        },
+        projectKey: 'CK',
       });
     });
   });
diff --git a/x-pack/test/api_integration/apis/maps/index.js b/x-pack/test/api_integration/apis/maps/index.js
index 9f1fe96c5637b..36a8fa2ec045e 100644
--- a/x-pack/test/api_integration/apis/maps/index.js
+++ b/x-pack/test/api_integration/apis/maps/index.js
@@ -18,6 +18,7 @@ export default function ({ loadTestFile, getService }) {
       loadTestFile(require.resolve('./migrations'));
       loadTestFile(require.resolve('./get_tile'));
       loadTestFile(require.resolve('./get_grid_tile'));
+      loadTestFile(require.resolve('./proxy_api'));
     });
   });
 }
diff --git a/x-pack/test/api_integration/apis/maps/proxy_api.js b/x-pack/test/api_integration/apis/maps/proxy_api.js
new file mode 100644
index 0000000000000..f85de9dc1670a
--- /dev/null
+++ b/x-pack/test/api_integration/apis/maps/proxy_api.js
@@ -0,0 +1,28 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import expect from '@kbn/expect';
+
+export default function ({ getService }) {
+  const supertest = getService('supertest');
+
+  describe('EMS proxy', () => {
+    it('should correctly rewrite url and format', async () => {
+      const resp = await supertest
+        .get(`/api/maps/ems/files/v7.10/manifest`)
+        .set('kbn-xsrf', 'kibana')
+        .expect(200);
+
+      expect(resp.body.layers.length).to.be.greaterThan(0);
+
+      //Check world-layer
+      const worldLayer = resp.body.layers.find((layer) => layer.layer_id === 'world_countries');
+      expect(worldLayer.formats.length).to.be.greaterThan(0);
+      expect(worldLayer.formats[0].type).to.be('geojson');
+      expect(worldLayer.formats[0].url).to.be('file?id=world_countries');
+    });
+  });
+}
diff --git a/x-pack/test/api_integration/config.ts b/x-pack/test/api_integration/config.ts
index 97fd968ce7992..fc021ffa0ca5b 100644
--- a/x-pack/test/api_integration/config.ts
+++ b/x-pack/test/api_integration/config.ts
@@ -25,6 +25,7 @@ export async function getApiIntegrationConfig({ readConfigFile }: FtrConfigProvi
       ...xPackFunctionalTestsConfig.get('kbnTestServer'),
       serverArgs: [
         ...xPackFunctionalTestsConfig.get('kbnTestServer.serverArgs'),
+        '--map.proxyElasticMapsServiceInMaps=true',
         '--xpack.security.session.idleTimeout=3600000', // 1 hour
         '--telemetry.optIn=true',
         '--xpack.fleet.enabled=true',
diff --git a/x-pack/test/apm_api_integration/basic/tests/correlations/slow_durations.ts b/x-pack/test/apm_api_integration/basic/tests/correlations/slow_durations.ts
index ada67bbec070b..085a81c5f1bf4 100644
--- a/x-pack/test/apm_api_integration/basic/tests/correlations/slow_durations.ts
+++ b/x-pack/test/apm_api_integration/basic/tests/correlations/slow_durations.ts
@@ -25,7 +25,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
     'user.username,user.id,host.ip,user_agent.name,kubernetes.pod.uuid,url.domain,container.id,service.node.name';
 
   // Failing: See https://github.com/elastic/kibana/issues/81264
-  describe.skip('Slow durations', () => {
+  describe('Slow durations', () => {
     const url = format({
       pathname: `/api/apm/correlations/slow_durations`,
       query: { start, end, durationPercentile, fieldNames },
@@ -40,21 +40,21 @@ export default function ApiTest({ getService }: FtrProviderContext) {
       });
     });
 
-    describe('with default scoring', () => {
-      let response: PromiseReturnType<typeof supertest.get>;
-      before(async () => {
-        await esArchiver.load(archiveName);
-        response = await supertest.get(url);
-      });
-
+    describe('when data is loaded', () => {
+      before(() => esArchiver.load(archiveName));
       after(() => esArchiver.unload(archiveName));
 
-      it('returns successfully', () => {
-        expect(response.status).to.eql(200);
-      });
+      describe('making request with default args', () => {
+        let response: PromiseReturnType<typeof supertest.get>;
+        before(async () => {
+          response = await supertest.get(url);
+
+          it('returns successfully', () => {
+            expect(response.status).to.eql(200);
+          });
 
-      it('returns fields in response', () => {
-        expectSnapshot(Object.keys(response.body.response)).toMatchInline(`
+          it('returns fields in response', () => {
+            expectSnapshot(Object.keys(response.body.response)).toMatchInline(`
           Array [
             "service.node.name",
             "host.ip",
@@ -64,14 +64,14 @@ export default function ApiTest({ getService }: FtrProviderContext) {
             "url.domain",
           ]
         `);
-      });
+          });
 
-      it('returns cardinality for each field', () => {
-        const cardinalitys = Object.values(response.body.response).map(
-          (field: any) => field.cardinality
-        );
+          it('returns cardinality for each field', () => {
+            const cardinalitys = Object.values(response.body.response).map(
+              (field: any) => field.cardinality
+            );
 
-        expectSnapshot(cardinalitys).toMatchInline(`
+            expectSnapshot(cardinalitys).toMatchInline(`
           Array [
             5,
             6,
@@ -81,11 +81,11 @@ export default function ApiTest({ getService }: FtrProviderContext) {
             4,
           ]
         `);
-      });
+          });
 
-      it('returns buckets', () => {
-        const { buckets } = response.body.response['user.id'].value;
-        expectSnapshot(buckets[0]).toMatchInline(`
+          it('returns buckets', () => {
+            const { buckets } = response.body.response['user.id'].value;
+            expectSnapshot(buckets[0]).toMatchInline(`
           Object {
             "bg_count": 32,
             "doc_count": 6,
@@ -93,46 +93,23 @@ export default function ApiTest({ getService }: FtrProviderContext) {
             "score": 0.1875,
           }
         `);
+          });
+        });
       });
-    });
 
-    describe('with different scoring', () => {
-      before(async () => esArchiver.load(archiveName));
-      after(() => esArchiver.unload(archiveName));
-
-      it(`returns buckets for each score`, async () => {
-        const promises = ['percentage', 'jlh', 'chi_square', 'gnd'].map(async (scoring) => {
-          const response = await supertest.get(
-            format({
-              pathname: `/api/apm/correlations/slow_durations`,
-              query: { start, end, durationPercentile, fieldNames, scoring },
-            })
-          );
-
-          return { name: scoring, value: response.body.response['user.id'].value.buckets[0].score };
+      describe('making a request for each "scoring"', () => {
+        ['percentage', 'jlh', 'chi_square', 'gnd'].map(async (scoring) => {
+          it(`returns response for scoring "${scoring}"`, async () => {
+            const response = await supertest.get(
+              format({
+                pathname: `/api/apm/correlations/slow_durations`,
+                query: { start, end, durationPercentile, fieldNames, scoring },
+              })
+            );
+
+            expect(response.status).to.be(200);
+          });
         });
-
-        const res = await Promise.all(promises);
-        expectSnapshot(res).toMatchInline(`
-          Array [
-            Object {
-              "name": "percentage",
-              "value": 0.1875,
-            },
-            Object {
-              "name": "jlh",
-              "value": 3.33506905769659,
-            },
-            Object {
-              "name": "chi_square",
-              "value": 219.192006524483,
-            },
-            Object {
-              "name": "gnd",
-              "value": 0.671406580688819,
-            },
-          ]
-        `);
       });
     });
   });
diff --git a/x-pack/test/functional/apps/dashboard/async_search/async_search.ts b/x-pack/test/functional/apps/dashboard/async_search/async_search.ts
index 004e51e459caa..6932a88635a67 100644
--- a/x-pack/test/functional/apps/dashboard/async_search/async_search.ts
+++ b/x-pack/test/functional/apps/dashboard/async_search/async_search.ts
@@ -8,10 +8,20 @@ import expect from '@kbn/expect';
 import { FtrProviderContext } from '../../../ftr_provider_context';
 
 export default function ({ getService, getPageObjects }: FtrProviderContext) {
+  const es = getService('es');
   const testSubjects = getService('testSubjects');
+  const log = getService('log');
   const PageObjects = getPageObjects(['common', 'header', 'dashboard', 'visChart']);
 
   describe('dashboard with async search', () => {
+    before(async function () {
+      const { body } = await es.info();
+      if (!body.version.number.includes('SNAPSHOT')) {
+        log.debug('Skipping because this build does not have the required shard_delay agg');
+        this.skip();
+      }
+    });
+
     it('not delayed should load', async () => {
       await PageObjects.common.navigateToApp('dashboard');
       await PageObjects.dashboard.gotoDashboardEditMode('Not Delayed');
diff --git a/x-pack/test/functional/apps/lens/persistent_context.ts b/x-pack/test/functional/apps/lens/persistent_context.ts
index 15515df92a89f..8d536aac3f795 100644
--- a/x-pack/test/functional/apps/lens/persistent_context.ts
+++ b/x-pack/test/functional/apps/lens/persistent_context.ts
@@ -66,5 +66,28 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
       expect(timeRange.end).to.equal('Sep 19, 2025 @ 06:31:44.000');
       await filterBar.hasFilter('ip', '97.220.3.248', false, true);
     });
+
+    it('keeps time range and pinned filters after refreshing directly after saving', async () => {
+      // restore defaults so visualization becomes saveable
+      await security.testUser.restoreDefaults();
+      await PageObjects.lens.configureDimension({
+        dimension: 'lnsXY_xDimensionPanel > lns-empty-dimension',
+        operation: 'date_histogram',
+        field: '@timestamp',
+      });
+
+      await PageObjects.lens.configureDimension({
+        dimension: 'lnsXY_yDimensionPanel > lns-empty-dimension',
+        operation: 'avg',
+        field: 'bytes',
+      });
+      await PageObjects.lens.save('persistentcontext');
+      await browser.refresh();
+      await PageObjects.header.waitUntilLoadingHasFinished();
+      const timeRange = await PageObjects.timePicker.getTimeConfig();
+      expect(timeRange.start).to.equal('Sep 7, 2015 @ 06:31:44.000');
+      expect(timeRange.end).to.equal('Sep 19, 2025 @ 06:31:44.000');
+      await filterBar.hasFilter('ip', '97.220.3.248', false, true);
+    });
   });
 }
diff --git a/x-pack/test/functional/apps/maps/discover.js b/x-pack/test/functional/apps/maps/discover.js
index 8dbd98ed3af2f..6a2c1f8437698 100644
--- a/x-pack/test/functional/apps/maps/discover.js
+++ b/x-pack/test/functional/apps/maps/discover.js
@@ -36,6 +36,7 @@ export default function ({ getService, getPageObjects }) {
       expect(doesLayerExist).to.equal(true);
       const hits = await PageObjects.maps.getHits();
       expect(hits).to.equal('4');
+      await PageObjects.maps.refreshAndClearUnsavedChangesWarning();
     });
 
     it('should link geo_point fields to Maps application with time and query context', async () => {
@@ -55,6 +56,7 @@ export default function ({ getService, getPageObjects }) {
       expect(doesLayerExist).to.equal(true);
       const hits = await PageObjects.maps.getHits();
       expect(hits).to.equal('7');
+      await PageObjects.maps.refreshAndClearUnsavedChangesWarning();
     });
   });
 }
diff --git a/x-pack/test/functional/apps/maps/joins.js b/x-pack/test/functional/apps/maps/joins.js
index bd5ecfe2a2504..0e2850dafbccc 100644
--- a/x-pack/test/functional/apps/maps/joins.js
+++ b/x-pack/test/functional/apps/maps/joins.js
@@ -38,6 +38,7 @@ export default function ({ getPageObjects, getService }) {
 
     after(async () => {
       await inspector.close();
+      await PageObjects.maps.refreshAndClearUnsavedChangesWarning();
       await security.testUser.restoreDefaults();
     });
 
diff --git a/x-pack/test/functional/apps/maps/layer_visibility.js b/x-pack/test/functional/apps/maps/layer_visibility.js
index dd9b93c995695..75a0e7da0f256 100644
--- a/x-pack/test/functional/apps/maps/layer_visibility.js
+++ b/x-pack/test/functional/apps/maps/layer_visibility.js
@@ -19,6 +19,7 @@ export default function ({ getPageObjects, getService }) {
 
     afterEach(async () => {
       await inspector.close();
+      await PageObjects.maps.refreshAndClearUnsavedChangesWarning();
       await security.testUser.restoreDefaults();
     });
 
diff --git a/x-pack/test/functional/apps/maps/vector_styling.js b/x-pack/test/functional/apps/maps/vector_styling.js
index 1def542982dd8..e4c5eaf892c76 100644
--- a/x-pack/test/functional/apps/maps/vector_styling.js
+++ b/x-pack/test/functional/apps/maps/vector_styling.js
@@ -16,6 +16,7 @@ export default function ({ getService, getPageObjects }) {
       await PageObjects.maps.loadSavedMap('document example');
     });
     after(async () => {
+      await PageObjects.maps.refreshAndClearUnsavedChangesWarning();
       await security.testUser.restoreDefaults();
     });
 
diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js b/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js
index c304b177cb04b..a58f66214e772 100644
--- a/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js
+++ b/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js
@@ -13,8 +13,7 @@ export default function ({ getService, getPageObjects }) {
   const nodesList = getService('monitoringElasticsearchNodes');
   const nodeDetail = getService('monitoringElasticsearchNodeDetail');
 
-  // Failing: See https://github.com/elastic/kibana/issues/81166
-  describe.skip('Elasticsearch node detail', () => {
+  describe('Elasticsearch node detail', () => {
     describe('Active Nodes', () => {
       const { setup, tearDown } = getLifecycleMethods(getService, getPageObjects);
 
diff --git a/x-pack/test/functional/page_objects/gis_page.ts b/x-pack/test/functional/page_objects/gis_page.ts
index 7be0aa425509e..408a50be8882e 100644
--- a/x-pack/test/functional/page_objects/gis_page.ts
+++ b/x-pack/test/functional/page_objects/gis_page.ts
@@ -19,6 +19,7 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte
   const queryBar = getService('queryBar');
   const comboBox = getService('comboBox');
   const renderable = getService('renderable');
+  const browser = getService('browser');
 
   function escapeLayerName(layerName: string) {
     return layerName.split(' ').join('_');
@@ -692,6 +693,13 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte
       }
       await testSubjects.click('mapSettingSubmitButton');
     }
+
+    async refreshAndClearUnsavedChangesWarning() {
+      await browser.refresh();
+      // accept alert if it pops up
+      const alert = await browser.getAlert();
+      await alert?.accept();
+    }
   }
   return new GisPage();
 }
diff --git a/x-pack/test/plugin_api_integration/plugins/sample_task_plugin/server/plugin.ts b/x-pack/test/plugin_api_integration/plugins/sample_task_plugin/server/plugin.ts
index 803df6a66ea58..b5d2c98d8cbcd 100644
--- a/x-pack/test/plugin_api_integration/plugins/sample_task_plugin/server/plugin.ts
+++ b/x-pack/test/plugin_api_integration/plugins/sample_task_plugin/server/plugin.ts
@@ -4,6 +4,7 @@
  * you may not use this file except in compliance with the Elastic License.
  */
 
+import _ from 'lodash';
 import { Plugin, CoreSetup, CoreStart } from 'src/core/server';
 import { EventEmitter } from 'events';
 import { Subject } from 'rxjs';
@@ -103,6 +104,29 @@ export class SampleTaskManagerFixturePlugin
         // fail after the first failed run
         maxAttempts: 1,
       },
+      sampleRecurringTaskTimingOut: {
+        title: 'Sample Recurring Task that Times Out',
+        description: 'A sample task that times out each run.',
+        maxAttempts: 3,
+        timeout: '1s',
+        createTaskRunner: () => ({
+          async run() {
+            return await new Promise((resolve) => {});
+          },
+        }),
+      },
+      sampleOneTimeTaskTimingOut: {
+        title: 'Sample One-Time Task that Times Out',
+        description: 'A sample task that times out each run.',
+        maxAttempts: 3,
+        timeout: '1s',
+        getRetry: (attempts: number, error: object) => new Date(Date.now() + _.random(2, 5) * 1000),
+        createTaskRunner: () => ({
+          async run() {
+            return await new Promise((resolve) => {});
+          },
+        }),
+      },
     });
 
     taskManager.addMiddleware({
diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js
index c87a5039360b8..560e4dd87daa3 100644
--- a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js
+++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js
@@ -607,5 +607,34 @@ export default function ({ getService }) {
         expect(getTaskById(tasks, longRunningTask.id).state.count).to.eql(1);
       });
     });
+
+    it('should mark non-recurring task as failed if task is still running but maxAttempts has been reached', async () => {
+      const task = await scheduleTask({
+        taskType: 'sampleOneTimeTaskTimingOut',
+        params: {},
+      });
+
+      await retry.try(async () => {
+        const [scheduledTask] = (await currentTasks()).docs;
+        expect(scheduledTask.id).to.eql(task.id);
+        expect(scheduledTask.status).to.eql('failed');
+        expect(scheduledTask.attempts).to.eql(3);
+      });
+    });
+
+    it('should continue claiming recurring task even if maxAttempts has been reached', async () => {
+      const task = await scheduleTask({
+        taskType: 'sampleRecurringTaskTimingOut',
+        schedule: { interval: '1s' },
+        params: {},
+      });
+
+      await retry.try(async () => {
+        const [scheduledTask] = (await currentTasks()).docs;
+        expect(scheduledTask.id).to.eql(task.id);
+        expect(scheduledTask.status).to.eql('claiming');
+        expect(scheduledTask.attempts).to.eql(4);
+      });
+    });
   });
 }
diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json
index 297eb2e9b4540..7bd38ea4afab7 100644
--- a/x-pack/test/tsconfig.json
+++ b/x-pack/test/tsconfig.json
@@ -26,6 +26,7 @@
     { "path": "../../src/plugins/telemetry_collection_manager/tsconfig.json" },
     { "path": "../../src/plugins/telemetry/tsconfig.json" },
     { "path": "../../src/plugins/kibana_usage_collection/tsconfig.json" },
+    { "path": "../plugins/telemetry_collection_xpack/tsconfig.json" },
     { "path": "../../src/plugins/newsfeed/tsconfig.json" }
   ]
 }
diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json
index 79309369386cf..382d4c073d41e 100644
--- a/x-pack/tsconfig.json
+++ b/x-pack/tsconfig.json
@@ -13,7 +13,8 @@
     "plugins/apm/e2e/cypress/**/*",
     "plugins/apm/scripts/**/*",
     "plugins/licensing/**/*",
-    "plugins/global_search/**/*"
+    "plugins/global_search/**/*",
+    "plugins/telemetry_collection_xpack/**/*"
   ],
   "compilerOptions": {
     "paths": {
@@ -35,6 +36,7 @@
     { "path": "../src/plugins/telemetry_collection_manager/tsconfig.json" },
     { "path": "../src/plugins/telemetry/tsconfig.json" },
     { "path": "../src/plugins/kibana_usage_collection/tsconfig.json" },
+    { "path": "./plugins/telemetry_collection_xpack/tsconfig.json" },
     { "path": "../src/plugins/newsfeed/tsconfig.json" },
   ]
 }
diff --git a/x-pack/tsconfig.refs.json b/x-pack/tsconfig.refs.json
index a389bbcf0272b..a4dfa15a3d8ab 100644
--- a/x-pack/tsconfig.refs.json
+++ b/x-pack/tsconfig.refs.json
@@ -3,5 +3,6 @@
   "references": [
     { "path": "./plugins/licensing/tsconfig.json" },
     { "path": "./plugins/global_search/tsconfig.json" },
+    { "path": "./plugins/telemetry_collection_xpack/tsconfig.json" },
   ]
 }
diff --git a/yarn.lock b/yarn.lock
index e986b46fbe110..18f868440f508 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1218,10 +1218,10 @@
   dependencies:
     "@elastic/apm-rum-core" "^5.7.0"
 
-"@elastic/charts@23.2.1":
-  version "23.2.1"
-  resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-23.2.1.tgz#1f48629fe4597655a7f119fd019c4d5a2cbaf252"
-  integrity sha512-L2jUPAWwE0xLry6DcqcngVLCa9R32pfz5jW1fyOJRWSq1Fay2swOw4joBe8PmHpvl2s8EwWi9qWBORR1z3hUeQ==
+"@elastic/charts@24.0.0":
+  version "24.0.0"
+  resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-24.0.0.tgz#7b97b00a3dc873f46f764de0f28573e236b76aa7"
+  integrity sha512-ZFIdHcU48Wes7eb1R+48L7xLH4p7D9oSdkoX/iuwt+znD353UhiYK9u+dbrpMXeOMtFYt7dktzVAbouHcJCZPA==
   dependencies:
     "@popperjs/core" "^2.4.0"
     chroma-js "^2.1.0"