diff --git a/api_docs/alerting.json b/api_docs/alerting.json
index 13a150d0af00d..979f444659c20 100644
--- a/api_docs/alerting.json
+++ b/api_docs/alerting.json
@@ -5,7 +5,42 @@
     "functions": [],
     "interfaces": [],
     "enums": [],
-    "misc": [],
+    "misc": [
+      {
+        "parentPluginId": "alerting",
+        "id": "def-public.AlertNavigationHandler",
+        "type": "Type",
+        "tags": [],
+        "label": "AlertNavigationHandler",
+        "description": [
+          "\nReturns information that can be used to navigate to a specific page to view the given rule.\n"
+        ],
+        "signature": [
+          "(alert: Pick<",
+          {
+            "pluginId": "alerting",
+            "scope": "common",
+            "docId": "kibAlertingPluginApi",
+            "section": "def-common.Alert",
+            "text": "Alert"
+          },
+          "<never>, \"enabled\" | \"id\" | \"name\" | \"params\" | \"actions\" | \"tags\" | \"alertTypeId\" | \"consumer\" | \"schedule\" | \"scheduledTaskId\" | \"createdBy\" | \"updatedBy\" | \"createdAt\" | \"updatedAt\" | \"apiKeyOwner\" | \"throttle\" | \"notifyWhen\" | \"muteAll\" | \"mutedInstanceIds\" | \"executionStatus\">) => string | ",
+          {
+            "pluginId": "kibanaUtils",
+            "scope": "common",
+            "docId": "kibKibanaUtilsPluginApi",
+            "section": "def-common.JsonObject",
+            "text": "JsonObject"
+          }
+        ],
+        "source": {
+          "path": "x-pack/plugins/alerting/public/alert_navigation_registry/types.ts",
+          "lineNumber": 20
+        },
+        "deprecated": false,
+        "initialIsOpen": false
+      }
+    ],
     "objects": [],
     "setup": {
       "parentPluginId": "alerting",
@@ -24,44 +59,58 @@
           "parentPluginId": "alerting",
           "id": "def-public.PluginSetupContract.registerNavigation",
           "type": "Function",
-          "tags": [],
+          "tags": [
+            "throws"
+          ],
           "label": "registerNavigation",
-          "description": [],
+          "description": [
+            "\nRegister a customized view of the particular rule type. Stack Management provides a generic overview, but a developer can register a\ncustom navigation to provide the user an extra link to a more curated view. The alerting plugin doesn't actually do\nanything with this information, but it can be used by other plugins via the `getNavigation` functionality. Currently\nthe trigger_actions_ui plugin uses it to expose the link from the generic rule view in Stack Management.\n"
+          ],
           "signature": [
-            "(consumer: string, alertType: string, handler: ",
-            "AlertNavigationHandler",
+            "(applicationId: string, ruleType: string, handler: ",
+            {
+              "pluginId": "alerting",
+              "scope": "public",
+              "docId": "kibAlertingPluginApi",
+              "section": "def-public.AlertNavigationHandler",
+              "text": "AlertNavigationHandler"
+            },
             ") => void"
           ],
           "source": {
             "path": "x-pack/plugins/alerting/public/plugin.ts",
-            "lineNumber": 15
+            "lineNumber": 30
           },
           "deprecated": false,
           "returnComment": [],
           "children": [
             {
               "parentPluginId": "alerting",
-              "id": "def-public.consumer",
+              "id": "def-public.applicationId",
               "type": "string",
               "tags": [],
-              "label": "consumer",
-              "description": [],
+              "label": "applicationId",
+              "description": [
+                "The application id that the user should be navigated to, to view a particular alert in a custom way."
+              ],
               "source": {
                 "path": "x-pack/plugins/alerting/public/plugin.ts",
-                "lineNumber": 16
+                "lineNumber": 31
               },
               "deprecated": false
             },
             {
               "parentPluginId": "alerting",
-              "id": "def-public.alertType",
+              "id": "def-public.ruleType",
               "type": "string",
               "tags": [],
-              "label": "alertType",
-              "description": [],
+              "label": "ruleType",
+              "description": [
+                "The rule type that has been registered with Alerting.Server.PluginSetupContract.registerType. If\nno such rule with that id exists, a warning is output to the console log. It used to throw an error, but that was temporarily moved\nbecause it was causing flaky test failures with https://github.com/elastic/kibana/issues/59229 and needs to be\ninvestigated more."
+              ],
               "source": {
                 "path": "x-pack/plugins/alerting/public/plugin.ts",
-                "lineNumber": 17
+                "lineNumber": 32
               },
               "deprecated": false
             },
@@ -71,7 +120,9 @@
               "type": "Function",
               "tags": [],
               "label": "handler",
-              "description": [],
+              "description": [
+                "The navigation handler should return either a relative URL, or a state object. This information can be used,\nin conjunction with the consumer id, to navigate the user to a custom URL to view a rule's details."
+              ],
               "signature": [
                 "(alert: Pick<",
                 {
@@ -81,15 +132,7 @@
                   "section": "def-common.Alert",
                   "text": "Alert"
                 },
-                "<never>, \"enabled\" | \"id\" | \"name\" | \"params\" | \"actions\" | \"tags\" | \"alertTypeId\" | \"consumer\" | \"schedule\" | \"scheduledTaskId\" | \"createdBy\" | \"updatedBy\" | \"createdAt\" | \"updatedAt\" | \"apiKeyOwner\" | \"throttle\" | \"notifyWhen\" | \"muteAll\" | \"mutedInstanceIds\" | \"executionStatus\">, alertType: ",
-                {
-                  "pluginId": "alerting",
-                  "scope": "common",
-                  "docId": "kibAlertingPluginApi",
-                  "section": "def-common.AlertType",
-                  "text": "AlertType"
-                },
-                "<\"default\", \"recovered\">) => string | ",
+                "<never>, \"enabled\" | \"id\" | \"name\" | \"params\" | \"actions\" | \"tags\" | \"alertTypeId\" | \"consumer\" | \"schedule\" | \"scheduledTaskId\" | \"createdBy\" | \"updatedBy\" | \"createdAt\" | \"updatedAt\" | \"apiKeyOwner\" | \"throttle\" | \"notifyWhen\" | \"muteAll\" | \"mutedInstanceIds\" | \"executionStatus\">) => string | ",
                 {
                   "pluginId": "kibanaUtils",
                   "scope": "common",
@@ -100,7 +143,7 @@
               ],
               "source": {
                 "path": "x-pack/plugins/alerting/public/plugin.ts",
-                "lineNumber": 18
+                "lineNumber": 33
               },
               "deprecated": false
             }
@@ -112,29 +155,39 @@
           "type": "Function",
           "tags": [],
           "label": "registerDefaultNavigation",
-          "description": [],
+          "description": [
+            "\nRegister a customized view for all rule types. Stack Management provides a generic overview, but a developer can register a\ncustom navigation to provide the user an extra link to a more curated view. The alerting plugin doesn't actually do\nanything with this information, but it can be used by other plugins via the `getNavigation` functionality. Currently\nthe trigger_actions_ui plugin uses it to expose the link from the generic rule view in Stack Management.\n"
+          ],
           "signature": [
-            "(consumer: string, handler: ",
-            "AlertNavigationHandler",
+            "(applicationId: string, handler: ",
+            {
+              "pluginId": "alerting",
+              "scope": "public",
+              "docId": "kibAlertingPluginApi",
+              "section": "def-public.AlertNavigationHandler",
+              "text": "AlertNavigationHandler"
+            },
             ") => void"
           ],
           "source": {
             "path": "x-pack/plugins/alerting/public/plugin.ts",
-            "lineNumber": 20
+            "lineNumber": 46
           },
           "deprecated": false,
           "returnComment": [],
           "children": [
             {
               "parentPluginId": "alerting",
-              "id": "def-public.consumer",
+              "id": "def-public.applicationId",
               "type": "string",
               "tags": [],
-              "label": "consumer",
-              "description": [],
+              "label": "applicationId",
+              "description": [
+                "The application id that the user should be navigated to, to view a particular alert in a custom way."
+              ],
               "source": {
                 "path": "x-pack/plugins/alerting/public/plugin.ts",
-                "lineNumber": 20
+                "lineNumber": 46
               },
               "deprecated": false
             },
@@ -144,7 +197,9 @@
               "type": "Function",
               "tags": [],
               "label": "handler",
-              "description": [],
+              "description": [
+                "The navigation handler should return either a relative URL, or a state object. This information can be used,\nin conjunction with the consumer id, to navigate the user to a custom URL to view a rule's details."
+              ],
               "signature": [
                 "(alert: Pick<",
                 {
@@ -154,15 +209,7 @@
                   "section": "def-common.Alert",
                   "text": "Alert"
                 },
-                "<never>, \"enabled\" | \"id\" | \"name\" | \"params\" | \"actions\" | \"tags\" | \"alertTypeId\" | \"consumer\" | \"schedule\" | \"scheduledTaskId\" | \"createdBy\" | \"updatedBy\" | \"createdAt\" | \"updatedAt\" | \"apiKeyOwner\" | \"throttle\" | \"notifyWhen\" | \"muteAll\" | \"mutedInstanceIds\" | \"executionStatus\">, alertType: ",
-                {
-                  "pluginId": "alerting",
-                  "scope": "common",
-                  "docId": "kibAlertingPluginApi",
-                  "section": "def-common.AlertType",
-                  "text": "AlertType"
-                },
-                "<\"default\", \"recovered\">) => string | ",
+                "<never>, \"enabled\" | \"id\" | \"name\" | \"params\" | \"actions\" | \"tags\" | \"alertTypeId\" | \"consumer\" | \"schedule\" | \"scheduledTaskId\" | \"createdBy\" | \"updatedBy\" | \"createdAt\" | \"updatedAt\" | \"apiKeyOwner\" | \"throttle\" | \"notifyWhen\" | \"muteAll\" | \"mutedInstanceIds\" | \"executionStatus\">) => string | ",
                 {
                   "pluginId": "kibanaUtils",
                   "scope": "common",
@@ -173,7 +220,7 @@
               ],
               "source": {
                 "path": "x-pack/plugins/alerting/public/plugin.ts",
-                "lineNumber": 20
+                "lineNumber": 46
               },
               "deprecated": false
             }
@@ -192,7 +239,7 @@
       "description": [],
       "source": {
         "path": "x-pack/plugins/alerting/public/plugin.ts",
-        "lineNumber": 22
+        "lineNumber": 48
       },
       "deprecated": false,
       "children": [
@@ -224,7 +271,7 @@
           ],
           "source": {
             "path": "x-pack/plugins/alerting/public/plugin.ts",
-            "lineNumber": 23
+            "lineNumber": 49
           },
           "deprecated": false,
           "returnComment": [],
@@ -238,7 +285,7 @@
               "description": [],
               "source": {
                 "path": "x-pack/plugins/alerting/public/plugin.ts",
-                "lineNumber": 23
+                "lineNumber": 49
               },
               "deprecated": false
             }
@@ -3857,7 +3904,7 @@
         "label": "ReservedActionGroups",
         "description": [],
         "signature": [
-          "\"recovered\" | RecoveryActionGroupId"
+          "RecoveryActionGroupId | \"recovered\""
         ],
         "source": {
           "path": "x-pack/plugins/alerting/common/builtin_action_groups.ts",
diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx
index 5dce4a9a2c7b1..c3c844148106f 100644
--- a/api_docs/alerting.mdx
+++ b/api_docs/alerting.mdx
@@ -29,6 +29,9 @@ import alertingObj from './alerting.json';
 ### Start
 <DocDefinitionList data={[alertingObj.client.start]}/>
 
+### Consts, variables and types
+<DocDefinitionList data={alertingObj.client.misc}/>
+
 ## Server
 
 ### Functions
diff --git a/api_docs/cases.json b/api_docs/cases.json
index bc92995dff6e9..cccf5de2710e2 100644
--- a/api_docs/cases.json
+++ b/api_docs/cases.json
@@ -34,21 +34,9 @@
             "text": "CasesUiStart"
           },
           ", ",
-          {
-            "pluginId": "cases",
-            "scope": "public",
-            "docId": "kibCasesPluginApi",
-            "section": "def-public.SetupPlugins",
-            "text": "SetupPlugins"
-          },
+          "SetupPlugins",
           ", ",
-          {
-            "pluginId": "cases",
-            "scope": "public",
-            "docId": "kibCasesPluginApi",
-            "section": "def-public.StartPlugins",
-            "text": "StartPlugins"
-          },
+          "StartPlugins",
           ">"
         ],
         "source": {
@@ -117,13 +105,7 @@
                 "text": "CoreSetup"
               },
               "<object, unknown>, plugins: ",
-              {
-                "pluginId": "cases",
-                "scope": "public",
-                "docId": "kibCasesPluginApi",
-                "section": "def-public.SetupPlugins",
-                "text": "SetupPlugins"
-              },
+              "SetupPlugins",
               ") => void"
             ],
             "source": {
@@ -164,13 +146,7 @@
                 "label": "plugins",
                 "description": [],
                 "signature": [
-                  {
-                    "pluginId": "cases",
-                    "scope": "public",
-                    "docId": "kibCasesPluginApi",
-                    "section": "def-public.SetupPlugins",
-                    "text": "SetupPlugins"
-                  }
+                  "SetupPlugins"
                 ],
                 "source": {
                   "path": "x-pack/plugins/cases/public/plugin.ts",
@@ -199,127 +175,676 @@
                 "text": "CoreStart"
               },
               ", plugins: ",
+              "StartPlugins",
+              ") => ",
+              {
+                "pluginId": "cases",
+                "scope": "public",
+                "docId": "kibCasesPluginApi",
+                "section": "def-public.CasesUiStart",
+                "text": "CasesUiStart"
+              }
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/plugin.ts",
+              "lineNumber": 38
+            },
+            "deprecated": false,
+            "children": [
+              {
+                "parentPluginId": "cases",
+                "id": "def-public.CasesUiPlugin.start.$1",
+                "type": "Object",
+                "tags": [],
+                "label": "core",
+                "description": [],
+                "signature": [
+                  {
+                    "pluginId": "core",
+                    "scope": "public",
+                    "docId": "kibCorePluginApi",
+                    "section": "def-public.CoreStart",
+                    "text": "CoreStart"
+                  }
+                ],
+                "source": {
+                  "path": "x-pack/plugins/cases/public/plugin.ts",
+                  "lineNumber": 38
+                },
+                "deprecated": false,
+                "isRequired": true
+              },
+              {
+                "parentPluginId": "cases",
+                "id": "def-public.CasesUiPlugin.start.$2",
+                "type": "Object",
+                "tags": [],
+                "label": "plugins",
+                "description": [],
+                "signature": [
+                  "StartPlugins"
+                ],
+                "source": {
+                  "path": "x-pack/plugins/cases/public/plugin.ts",
+                  "lineNumber": 38
+                },
+                "deprecated": false,
+                "isRequired": true
+              }
+            ],
+            "returnComment": []
+          },
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.CasesUiPlugin.stop",
+            "type": "Function",
+            "tags": [],
+            "label": "stop",
+            "description": [],
+            "signature": [
+              "() => void"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/plugin.ts",
+              "lineNumber": 92
+            },
+            "deprecated": false,
+            "children": [],
+            "returnComment": []
+          }
+        ],
+        "initialIsOpen": false
+      }
+    ],
+    "functions": [],
+    "interfaces": [
+      {
+        "parentPluginId": "cases",
+        "id": "def-public.AllCasesProps",
+        "type": "Interface",
+        "tags": [],
+        "label": "AllCasesProps",
+        "description": [],
+        "signature": [
+          {
+            "pluginId": "cases",
+            "scope": "public",
+            "docId": "kibCasesPluginApi",
+            "section": "def-public.AllCasesProps",
+            "text": "AllCasesProps"
+          },
+          " extends ",
+          "Owner"
+        ],
+        "source": {
+          "path": "x-pack/plugins/cases/public/components/all_cases/index.tsx",
+          "lineNumber": 13
+        },
+        "deprecated": false,
+        "children": [
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.AllCasesProps.caseDetailsNavigation",
+            "type": "Object",
+            "tags": [],
+            "label": "caseDetailsNavigation",
+            "description": [],
+            "signature": [
+              "CasesNavigation",
+              "<",
+              "CaseDetailsHrefSchema",
+              ", \"configurable\">"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/all_cases/index.tsx",
+              "lineNumber": 14
+            },
+            "deprecated": false
+          },
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.AllCasesProps.configureCasesNavigation",
+            "type": "Object",
+            "tags": [],
+            "label": "configureCasesNavigation",
+            "description": [],
+            "signature": [
+              "CasesNavigation",
+              "<MouseEvent | React.MouseEvent<Element, MouseEvent>, null>"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/all_cases/index.tsx",
+              "lineNumber": 15
+            },
+            "deprecated": false
+          },
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.AllCasesProps.createCaseNavigation",
+            "type": "Object",
+            "tags": [],
+            "label": "createCaseNavigation",
+            "description": [],
+            "signature": [
+              "CasesNavigation",
+              "<MouseEvent | React.MouseEvent<Element, MouseEvent>, null>"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/all_cases/index.tsx",
+              "lineNumber": 16
+            },
+            "deprecated": false
+          },
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.AllCasesProps.userCanCrud",
+            "type": "boolean",
+            "tags": [],
+            "label": "userCanCrud",
+            "description": [],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/all_cases/index.tsx",
+              "lineNumber": 17
+            },
+            "deprecated": false
+          }
+        ],
+        "initialIsOpen": false
+      },
+      {
+        "parentPluginId": "cases",
+        "id": "def-public.AllCasesSelectorModalProps",
+        "type": "Interface",
+        "tags": [],
+        "label": "AllCasesSelectorModalProps",
+        "description": [],
+        "signature": [
+          {
+            "pluginId": "cases",
+            "scope": "public",
+            "docId": "kibCasesPluginApi",
+            "section": "def-public.AllCasesSelectorModalProps",
+            "text": "AllCasesSelectorModalProps"
+          },
+          " extends ",
+          "Owner"
+        ],
+        "source": {
+          "path": "x-pack/plugins/cases/public/components/all_cases/selector_modal/index.tsx",
+          "lineNumber": 23
+        },
+        "deprecated": false,
+        "children": [
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.AllCasesSelectorModalProps.alertData",
+            "type": "Object",
+            "tags": [],
+            "label": "alertData",
+            "description": [],
+            "signature": [
+              "Pick<{ type: ",
+              {
+                "pluginId": "cases",
+                "scope": "common",
+                "docId": "kibCasesPluginApi",
+                "section": "def-common.CommentType",
+                "text": "CommentType"
+              },
+              ".alert | ",
+              {
+                "pluginId": "cases",
+                "scope": "common",
+                "docId": "kibCasesPluginApi",
+                "section": "def-common.CommentType",
+                "text": "CommentType"
+              },
+              ".generatedAlert; alertId: string | string[]; index: string | string[]; rule: { id: string | null; name: string | null; }; owner: string; }, \"index\" | \"rule\" | \"alertId\" | \"owner\"> | undefined"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/all_cases/selector_modal/index.tsx",
+              "lineNumber": 24
+            },
+            "deprecated": false
+          },
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.AllCasesSelectorModalProps.createCaseNavigation",
+            "type": "Object",
+            "tags": [],
+            "label": "createCaseNavigation",
+            "description": [],
+            "signature": [
+              "CasesNavigation",
+              "<MouseEvent | React.MouseEvent<Element, MouseEvent>, null>"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/all_cases/selector_modal/index.tsx",
+              "lineNumber": 25
+            },
+            "deprecated": false
+          },
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.AllCasesSelectorModalProps.hiddenStatuses",
+            "type": "Array",
+            "tags": [],
+            "label": "hiddenStatuses",
+            "description": [],
+            "signature": [
+              {
+                "pluginId": "cases",
+                "scope": "common",
+                "docId": "kibCasesPluginApi",
+                "section": "def-common.CaseStatusWithAllStatus",
+                "text": "CaseStatusWithAllStatus"
+              },
+              "[] | undefined"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/all_cases/selector_modal/index.tsx",
+              "lineNumber": 26
+            },
+            "deprecated": false
+          },
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.AllCasesSelectorModalProps.onRowClick",
+            "type": "Function",
+            "tags": [],
+            "label": "onRowClick",
+            "description": [],
+            "signature": [
+              "(theCase?: ",
+              {
+                "pluginId": "cases",
+                "scope": "common",
+                "docId": "kibCasesPluginApi",
+                "section": "def-common.Case",
+                "text": "Case"
+              },
+              " | ",
+              {
+                "pluginId": "cases",
+                "scope": "common",
+                "docId": "kibCasesPluginApi",
+                "section": "def-common.SubCase",
+                "text": "SubCase"
+              },
+              " | undefined) => void"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/all_cases/selector_modal/index.tsx",
+              "lineNumber": 27
+            },
+            "deprecated": false,
+            "returnComment": [],
+            "children": [
+              {
+                "parentPluginId": "cases",
+                "id": "def-public.theCase",
+                "type": "CompoundType",
+                "tags": [],
+                "label": "theCase",
+                "description": [],
+                "signature": [
+                  {
+                    "pluginId": "cases",
+                    "scope": "common",
+                    "docId": "kibCasesPluginApi",
+                    "section": "def-common.Case",
+                    "text": "Case"
+                  },
+                  " | ",
+                  {
+                    "pluginId": "cases",
+                    "scope": "common",
+                    "docId": "kibCasesPluginApi",
+                    "section": "def-common.SubCase",
+                    "text": "SubCase"
+                  },
+                  " | undefined"
+                ],
+                "source": {
+                  "path": "x-pack/plugins/cases/public/components/all_cases/selector_modal/index.tsx",
+                  "lineNumber": 27
+                },
+                "deprecated": false
+              }
+            ]
+          },
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.AllCasesSelectorModalProps.updateCase",
+            "type": "Function",
+            "tags": [],
+            "label": "updateCase",
+            "description": [],
+            "signature": [
+              "((newCase: ",
+              {
+                "pluginId": "cases",
+                "scope": "common",
+                "docId": "kibCasesPluginApi",
+                "section": "def-common.Case",
+                "text": "Case"
+              },
+              ") => void) | undefined"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/all_cases/selector_modal/index.tsx",
+              "lineNumber": 28
+            },
+            "deprecated": false
+          },
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.AllCasesSelectorModalProps.userCanCrud",
+            "type": "boolean",
+            "tags": [],
+            "label": "userCanCrud",
+            "description": [],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/all_cases/selector_modal/index.tsx",
+              "lineNumber": 29
+            },
+            "deprecated": false
+          }
+        ],
+        "initialIsOpen": false
+      },
+      {
+        "parentPluginId": "cases",
+        "id": "def-public.CaseViewProps",
+        "type": "Interface",
+        "tags": [],
+        "label": "CaseViewProps",
+        "description": [],
+        "signature": [
+          {
+            "pluginId": "cases",
+            "scope": "public",
+            "docId": "kibCasesPluginApi",
+            "section": "def-public.CaseViewProps",
+            "text": "CaseViewProps"
+          },
+          " extends ",
+          "CaseViewComponentProps"
+        ],
+        "source": {
+          "path": "x-pack/plugins/cases/public/components/case_view/index.tsx",
+          "lineNumber": 63
+        },
+        "deprecated": false,
+        "children": [
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.CaseViewProps.onCaseDataSuccess",
+            "type": "Function",
+            "tags": [],
+            "label": "onCaseDataSuccess",
+            "description": [],
+            "signature": [
+              "((data: ",
+              {
+                "pluginId": "cases",
+                "scope": "common",
+                "docId": "kibCasesPluginApi",
+                "section": "def-common.Case",
+                "text": "Case"
+              },
+              ") => void) | undefined"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/case_view/index.tsx",
+              "lineNumber": 64
+            },
+            "deprecated": false
+          },
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.CaseViewProps.timelineIntegration",
+            "type": "Object",
+            "tags": [],
+            "label": "timelineIntegration",
+            "description": [],
+            "signature": [
+              "CasesTimelineIntegration",
+              " | undefined"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/case_view/index.tsx",
+              "lineNumber": 65
+            },
+            "deprecated": false
+          }
+        ],
+        "initialIsOpen": false
+      },
+      {
+        "parentPluginId": "cases",
+        "id": "def-public.ConfigureCasesProps",
+        "type": "Interface",
+        "tags": [],
+        "label": "ConfigureCasesProps",
+        "description": [],
+        "signature": [
+          {
+            "pluginId": "cases",
+            "scope": "public",
+            "docId": "kibCasesPluginApi",
+            "section": "def-public.ConfigureCasesProps",
+            "text": "ConfigureCasesProps"
+          },
+          " extends ",
+          "Owner"
+        ],
+        "source": {
+          "path": "x-pack/plugins/cases/public/components/configure_cases/index.tsx",
+          "lineNumber": 55
+        },
+        "deprecated": false,
+        "children": [
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.ConfigureCasesProps.userCanCrud",
+            "type": "boolean",
+            "tags": [],
+            "label": "userCanCrud",
+            "description": [],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/configure_cases/index.tsx",
+              "lineNumber": 56
+            },
+            "deprecated": false
+          }
+        ],
+        "initialIsOpen": false
+      },
+      {
+        "parentPluginId": "cases",
+        "id": "def-public.CreateCaseProps",
+        "type": "Interface",
+        "tags": [],
+        "label": "CreateCaseProps",
+        "description": [],
+        "signature": [
+          {
+            "pluginId": "cases",
+            "scope": "public",
+            "docId": "kibCasesPluginApi",
+            "section": "def-public.CreateCaseProps",
+            "text": "CreateCaseProps"
+          },
+          " extends ",
+          "Owner"
+        ],
+        "source": {
+          "path": "x-pack/plugins/cases/public/components/create/index.tsx",
+          "lineNumber": 34
+        },
+        "deprecated": false,
+        "children": [
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.CreateCaseProps.afterCaseCreated",
+            "type": "Function",
+            "tags": [],
+            "label": "afterCaseCreated",
+            "description": [],
+            "signature": [
+              "((theCase: ",
+              {
+                "pluginId": "cases",
+                "scope": "common",
+                "docId": "kibCasesPluginApi",
+                "section": "def-common.Case",
+                "text": "Case"
+              },
+              ", postComment: (args: PostComment) => Promise<void>) => Promise<void>) | undefined"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/create/index.tsx",
+              "lineNumber": 35
+            },
+            "deprecated": false
+          },
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.CreateCaseProps.caseType",
+            "type": "CompoundType",
+            "tags": [],
+            "label": "caseType",
+            "description": [],
+            "signature": [
+              {
+                "pluginId": "cases",
+                "scope": "common",
+                "docId": "kibCasesPluginApi",
+                "section": "def-common.CaseType",
+                "text": "CaseType"
+              },
+              " | undefined"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/create/index.tsx",
+              "lineNumber": 36
+            },
+            "deprecated": false
+          },
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.CreateCaseProps.hideConnectorServiceNowSir",
+            "type": "CompoundType",
+            "tags": [],
+            "label": "hideConnectorServiceNowSir",
+            "description": [],
+            "signature": [
+              "boolean | undefined"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/create/index.tsx",
+              "lineNumber": 37
+            },
+            "deprecated": false
+          },
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.CreateCaseProps.onCancel",
+            "type": "Function",
+            "tags": [],
+            "label": "onCancel",
+            "description": [],
+            "signature": [
+              "() => void"
+            ],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/create/index.tsx",
+              "lineNumber": 38
+            },
+            "deprecated": false,
+            "returnComment": [],
+            "children": []
+          },
+          {
+            "parentPluginId": "cases",
+            "id": "def-public.CreateCaseProps.onSuccess",
+            "type": "Function",
+            "tags": [],
+            "label": "onSuccess",
+            "description": [],
+            "signature": [
+              "(theCase: ",
               {
                 "pluginId": "cases",
-                "scope": "public",
+                "scope": "common",
                 "docId": "kibCasesPluginApi",
-                "section": "def-public.StartPlugins",
-                "text": "StartPlugins"
+                "section": "def-common.Case",
+                "text": "Case"
               },
-              ") => ",
-              {
-                "pluginId": "cases",
-                "scope": "public",
-                "docId": "kibCasesPluginApi",
-                "section": "def-public.CasesUiStart",
-                "text": "CasesUiStart"
-              }
+              ") => Promise<void>"
             ],
             "source": {
-              "path": "x-pack/plugins/cases/public/plugin.ts",
-              "lineNumber": 38
+              "path": "x-pack/plugins/cases/public/components/create/index.tsx",
+              "lineNumber": 39
             },
             "deprecated": false,
+            "returnComment": [],
             "children": [
               {
                 "parentPluginId": "cases",
-                "id": "def-public.CasesUiPlugin.start.$1",
-                "type": "Object",
-                "tags": [],
-                "label": "core",
-                "description": [],
-                "signature": [
-                  {
-                    "pluginId": "core",
-                    "scope": "public",
-                    "docId": "kibCorePluginApi",
-                    "section": "def-public.CoreStart",
-                    "text": "CoreStart"
-                  }
-                ],
-                "source": {
-                  "path": "x-pack/plugins/cases/public/plugin.ts",
-                  "lineNumber": 38
-                },
-                "deprecated": false,
-                "isRequired": true
-              },
-              {
-                "parentPluginId": "cases",
-                "id": "def-public.CasesUiPlugin.start.$2",
+                "id": "def-public.theCase",
                 "type": "Object",
                 "tags": [],
-                "label": "plugins",
+                "label": "theCase",
                 "description": [],
                 "signature": [
                   {
                     "pluginId": "cases",
-                    "scope": "public",
+                    "scope": "common",
                     "docId": "kibCasesPluginApi",
-                    "section": "def-public.StartPlugins",
-                    "text": "StartPlugins"
+                    "section": "def-common.Case",
+                    "text": "Case"
                   }
                 ],
                 "source": {
-                  "path": "x-pack/plugins/cases/public/plugin.ts",
-                  "lineNumber": 38
+                  "path": "x-pack/plugins/cases/public/components/create/index.tsx",
+                  "lineNumber": 39
                 },
-                "deprecated": false,
-                "isRequired": true
+                "deprecated": false
               }
-            ],
-            "returnComment": []
+            ]
           },
           {
             "parentPluginId": "cases",
-            "id": "def-public.CasesUiPlugin.stop",
-            "type": "Function",
+            "id": "def-public.CreateCaseProps.timelineIntegration",
+            "type": "Object",
             "tags": [],
-            "label": "stop",
+            "label": "timelineIntegration",
             "description": [],
             "signature": [
-              "() => void"
+              "CasesTimelineIntegration",
+              " | undefined"
             ],
             "source": {
-              "path": "x-pack/plugins/cases/public/plugin.ts",
-              "lineNumber": 92
+              "path": "x-pack/plugins/cases/public/components/create/index.tsx",
+              "lineNumber": 40
             },
-            "deprecated": false,
-            "children": [],
-            "returnComment": []
-          }
-        ],
-        "initialIsOpen": false
-      }
-    ],
-    "functions": [],
-    "interfaces": [
-      {
-        "parentPluginId": "cases",
-        "id": "def-public.Owner",
-        "type": "Interface",
-        "tags": [],
-        "label": "Owner",
-        "description": [],
-        "source": {
-          "path": "x-pack/plugins/cases/public/types.ts",
-          "lineNumber": 42
-        },
-        "deprecated": false,
-        "children": [
+            "deprecated": false
+          },
           {
             "parentPluginId": "cases",
-            "id": "def-public.Owner.owner",
-            "type": "Array",
+            "id": "def-public.CreateCaseProps.withSteps",
+            "type": "CompoundType",
             "tags": [],
-            "label": "owner",
+            "label": "withSteps",
             "description": [],
             "signature": [
-              "string[]"
+              "boolean | undefined"
             ],
             "source": {
-              "path": "x-pack/plugins/cases/public/types.ts",
-              "lineNumber": 43
+              "path": "x-pack/plugins/cases/public/components/create/index.tsx",
+              "lineNumber": 41
             },
             "deprecated": false
           }
@@ -328,148 +853,100 @@
       },
       {
         "parentPluginId": "cases",
-        "id": "def-public.SetupPlugins",
+        "id": "def-public.RecentCasesProps",
         "type": "Interface",
         "tags": [],
-        "label": "SetupPlugins",
+        "label": "RecentCasesProps",
         "description": [],
+        "signature": [
+          {
+            "pluginId": "cases",
+            "scope": "public",
+            "docId": "kibCasesPluginApi",
+            "section": "def-public.RecentCasesProps",
+            "text": "RecentCasesProps"
+          },
+          " extends ",
+          "Owner"
+        ],
         "source": {
-          "path": "x-pack/plugins/cases/public/types.ts",
-          "lineNumber": 22
+          "path": "x-pack/plugins/cases/public/components/recent_cases/index.tsx",
+          "lineNumber": 20
         },
         "deprecated": false,
         "children": [
           {
             "parentPluginId": "cases",
-            "id": "def-public.SetupPlugins.security",
+            "id": "def-public.RecentCasesProps.allCasesNavigation",
             "type": "Object",
             "tags": [],
-            "label": "security",
+            "label": "allCasesNavigation",
             "description": [],
             "signature": [
-              {
-                "pluginId": "security",
-                "scope": "public",
-                "docId": "kibSecurityPluginApi",
-                "section": "def-public.SecurityPluginSetup",
-                "text": "SecurityPluginSetup"
-              }
+              "CasesNavigation",
+              "<MouseEvent | React.MouseEvent<Element, MouseEvent>, null>"
             ],
             "source": {
-              "path": "x-pack/plugins/cases/public/types.ts",
-              "lineNumber": 23
+              "path": "x-pack/plugins/cases/public/components/recent_cases/index.tsx",
+              "lineNumber": 21
             },
             "deprecated": false
           },
           {
             "parentPluginId": "cases",
-            "id": "def-public.SetupPlugins.triggersActionsUi",
+            "id": "def-public.RecentCasesProps.caseDetailsNavigation",
             "type": "Object",
             "tags": [],
-            "label": "triggersActionsUi",
+            "label": "caseDetailsNavigation",
             "description": [],
             "signature": [
-              {
-                "pluginId": "triggersActionsUi",
-                "scope": "public",
-                "docId": "kibTriggersActionsUiPluginApi",
-                "section": "def-public.TriggersAndActionsUIPublicPluginSetup",
-                "text": "TriggersAndActionsUIPublicPluginSetup"
-              }
+              "CasesNavigation",
+              "<",
+              "CaseDetailsHrefSchema",
+              ", \"configurable\">"
             ],
             "source": {
-              "path": "x-pack/plugins/cases/public/types.ts",
-              "lineNumber": 24
+              "path": "x-pack/plugins/cases/public/components/recent_cases/index.tsx",
+              "lineNumber": 22
             },
             "deprecated": false
-          }
-        ],
-        "initialIsOpen": false
-      },
-      {
-        "parentPluginId": "cases",
-        "id": "def-public.StartPlugins",
-        "type": "Interface",
-        "tags": [],
-        "label": "StartPlugins",
-        "description": [],
-        "source": {
-          "path": "x-pack/plugins/cases/public/types.ts",
-          "lineNumber": 27
-        },
-        "deprecated": false,
-        "children": [
+          },
           {
             "parentPluginId": "cases",
-            "id": "def-public.StartPlugins.triggersActionsUi",
+            "id": "def-public.RecentCasesProps.createCaseNavigation",
             "type": "Object",
             "tags": [],
-            "label": "triggersActionsUi",
+            "label": "createCaseNavigation",
             "description": [],
             "signature": [
-              {
-                "pluginId": "triggersActionsUi",
-                "scope": "public",
-                "docId": "kibTriggersActionsUiPluginApi",
-                "section": "def-public.TriggersAndActionsUIPublicPluginStart",
-                "text": "TriggersAndActionsUIPublicPluginStart"
-              }
+              "CasesNavigation",
+              "<MouseEvent | React.MouseEvent<Element, MouseEvent>, null>"
             ],
             "source": {
-              "path": "x-pack/plugins/cases/public/types.ts",
-              "lineNumber": 28
+              "path": "x-pack/plugins/cases/public/components/recent_cases/index.tsx",
+              "lineNumber": 23
             },
             "deprecated": false
-          }
-        ],
-        "initialIsOpen": false
-      }
-    ],
-    "enums": [],
-    "misc": [
-      {
-        "parentPluginId": "cases",
-        "id": "def-public.StartServices",
-        "type": "Type",
-        "tags": [],
-        "label": "StartServices",
-        "description": [
-          "\nTODO: The extra security service is one that should be implemented in the kibana context of the consuming application.\nSecurity is needed for access to authc for the `useCurrentUser` hook. Security_Solution currently passes it via renderApp in public/plugin.tsx\nLeaving it out currently in lieu of RBAC changes"
-        ],
-        "signature": [
-          {
-            "pluginId": "core",
-            "scope": "public",
-            "docId": "kibCorePluginApi",
-            "section": "def-public.CoreStart",
-            "text": "CoreStart"
-          },
-          " & ",
-          {
-            "pluginId": "cases",
-            "scope": "public",
-            "docId": "kibCasesPluginApi",
-            "section": "def-public.StartPlugins",
-            "text": "StartPlugins"
           },
-          " & { security: ",
           {
-            "pluginId": "security",
-            "scope": "public",
-            "docId": "kibSecurityPluginApi",
-            "section": "def-public.SecurityPluginSetup",
-            "text": "SecurityPluginSetup"
-          },
-          "; }"
+            "parentPluginId": "cases",
+            "id": "def-public.RecentCasesProps.maxCasesToShow",
+            "type": "number",
+            "tags": [],
+            "label": "maxCasesToShow",
+            "description": [],
+            "source": {
+              "path": "x-pack/plugins/cases/public/components/recent_cases/index.tsx",
+              "lineNumber": 24
+            },
+            "deprecated": false
+          }
         ],
-        "source": {
-          "path": "x-pack/plugins/cases/public/types.ts",
-          "lineNumber": 37
-        },
-        "deprecated": false,
         "initialIsOpen": false
       }
     ],
+    "enums": [],
+    "misc": [],
     "objects": [],
     "start": {
       "parentPluginId": "cases",
@@ -490,20 +967,36 @@
           "type": "Function",
           "tags": [],
           "label": "getAllCases",
-          "description": [],
+          "description": [
+            "\nGet the all cases table"
+          ],
           "signature": [
             "(props: ",
-            "AllCasesProps",
+            {
+              "pluginId": "cases",
+              "scope": "public",
+              "docId": "kibCasesPluginApi",
+              "section": "def-public.AllCasesProps",
+              "text": "AllCasesProps"
+            },
             ") => React.ReactElement<",
-            "AllCasesProps",
+            {
+              "pluginId": "cases",
+              "scope": "public",
+              "docId": "kibCasesPluginApi",
+              "section": "def-public.AllCasesProps",
+              "text": "AllCasesProps"
+            },
             ">"
           ],
           "source": {
             "path": "x-pack/plugins/cases/public/types.ts",
-            "lineNumber": 47
+            "lineNumber": 52
           },
           "deprecated": false,
-          "returnComment": [],
+          "returnComment": [
+            "A react component that displays all cases"
+          ],
           "children": [
             {
               "parentPluginId": "cases",
@@ -511,13 +1004,21 @@
               "type": "Object",
               "tags": [],
               "label": "props",
-              "description": [],
-              "signature": [
+              "description": [
                 "AllCasesProps"
               ],
+              "signature": [
+                {
+                  "pluginId": "cases",
+                  "scope": "public",
+                  "docId": "kibCasesPluginApi",
+                  "section": "def-public.AllCasesProps",
+                  "text": "AllCasesProps"
+                }
+              ],
               "source": {
                 "path": "x-pack/plugins/cases/public/types.ts",
-                "lineNumber": 47
+                "lineNumber": 52
               },
               "deprecated": false
             }
@@ -529,20 +1030,36 @@
           "type": "Function",
           "tags": [],
           "label": "getAllCasesSelectorModal",
-          "description": [],
+          "description": [
+            "\nuse Modal hook for all cases selector"
+          ],
           "signature": [
             "(props: ",
-            "AllCasesSelectorModalProps",
+            {
+              "pluginId": "cases",
+              "scope": "public",
+              "docId": "kibCasesPluginApi",
+              "section": "def-public.AllCasesSelectorModalProps",
+              "text": "AllCasesSelectorModalProps"
+            },
             ") => React.ReactElement<",
-            "AllCasesSelectorModalProps",
+            {
+              "pluginId": "cases",
+              "scope": "public",
+              "docId": "kibCasesPluginApi",
+              "section": "def-public.AllCasesSelectorModalProps",
+              "text": "AllCasesSelectorModalProps"
+            },
             ">"
           ],
           "source": {
             "path": "x-pack/plugins/cases/public/types.ts",
-            "lineNumber": 48
+            "lineNumber": 58
           },
           "deprecated": false,
-          "returnComment": [],
+          "returnComment": [
+            "A react component that is a modal for selecting a case"
+          ],
           "children": [
             {
               "parentPluginId": "cases",
@@ -550,13 +1067,21 @@
               "type": "Object",
               "tags": [],
               "label": "props",
-              "description": [],
+              "description": [
+                "UseAllCasesSelectorModalProps"
+              ],
               "signature": [
-                "AllCasesSelectorModalProps"
+                {
+                  "pluginId": "cases",
+                  "scope": "public",
+                  "docId": "kibCasesPluginApi",
+                  "section": "def-public.AllCasesSelectorModalProps",
+                  "text": "AllCasesSelectorModalProps"
+                }
               ],
               "source": {
                 "path": "x-pack/plugins/cases/public/types.ts",
-                "lineNumber": 49
+                "lineNumber": 59
               },
               "deprecated": false
             }
@@ -568,20 +1093,36 @@
           "type": "Function",
           "tags": [],
           "label": "getCaseView",
-          "description": [],
+          "description": [
+            "\nGet the case view component"
+          ],
           "signature": [
             "(props: ",
-            "CaseViewProps",
+            {
+              "pluginId": "cases",
+              "scope": "public",
+              "docId": "kibCasesPluginApi",
+              "section": "def-public.CaseViewProps",
+              "text": "CaseViewProps"
+            },
             ") => React.ReactElement<",
-            "CaseViewProps",
+            {
+              "pluginId": "cases",
+              "scope": "public",
+              "docId": "kibCasesPluginApi",
+              "section": "def-public.CaseViewProps",
+              "text": "CaseViewProps"
+            },
             ">"
           ],
           "source": {
             "path": "x-pack/plugins/cases/public/types.ts",
-            "lineNumber": 51
+            "lineNumber": 66
           },
           "deprecated": false,
-          "returnComment": [],
+          "returnComment": [
+            "A react component for viewing a specific case"
+          ],
           "children": [
             {
               "parentPluginId": "cases",
@@ -589,13 +1130,21 @@
               "type": "Object",
               "tags": [],
               "label": "props",
-              "description": [],
-              "signature": [
+              "description": [
                 "CaseViewProps"
               ],
+              "signature": [
+                {
+                  "pluginId": "cases",
+                  "scope": "public",
+                  "docId": "kibCasesPluginApi",
+                  "section": "def-public.CaseViewProps",
+                  "text": "CaseViewProps"
+                }
+              ],
               "source": {
                 "path": "x-pack/plugins/cases/public/types.ts",
-                "lineNumber": 51
+                "lineNumber": 66
               },
               "deprecated": false
             }
@@ -607,20 +1156,36 @@
           "type": "Function",
           "tags": [],
           "label": "getConfigureCases",
-          "description": [],
+          "description": [
+            "\nGet the configure case component"
+          ],
           "signature": [
             "(props: ",
-            "ConfigureCasesProps",
+            {
+              "pluginId": "cases",
+              "scope": "public",
+              "docId": "kibCasesPluginApi",
+              "section": "def-public.ConfigureCasesProps",
+              "text": "ConfigureCasesProps"
+            },
             ") => React.ReactElement<",
-            "ConfigureCasesProps",
+            {
+              "pluginId": "cases",
+              "scope": "public",
+              "docId": "kibCasesPluginApi",
+              "section": "def-public.ConfigureCasesProps",
+              "text": "ConfigureCasesProps"
+            },
             ">"
           ],
           "source": {
             "path": "x-pack/plugins/cases/public/types.ts",
-            "lineNumber": 52
+            "lineNumber": 72
           },
           "deprecated": false,
-          "returnComment": [],
+          "returnComment": [
+            "A react component for configuring a specific case"
+          ],
           "children": [
             {
               "parentPluginId": "cases",
@@ -628,13 +1193,21 @@
               "type": "Object",
               "tags": [],
               "label": "props",
-              "description": [],
-              "signature": [
+              "description": [
                 "ConfigureCasesProps"
               ],
+              "signature": [
+                {
+                  "pluginId": "cases",
+                  "scope": "public",
+                  "docId": "kibCasesPluginApi",
+                  "section": "def-public.ConfigureCasesProps",
+                  "text": "ConfigureCasesProps"
+                }
+              ],
               "source": {
                 "path": "x-pack/plugins/cases/public/types.ts",
-                "lineNumber": 52
+                "lineNumber": 72
               },
               "deprecated": false
             }
@@ -646,20 +1219,36 @@
           "type": "Function",
           "tags": [],
           "label": "getCreateCase",
-          "description": [],
+          "description": [
+            "\nGet the create case form"
+          ],
           "signature": [
             "(props: ",
-            "CreateCaseProps",
+            {
+              "pluginId": "cases",
+              "scope": "public",
+              "docId": "kibCasesPluginApi",
+              "section": "def-public.CreateCaseProps",
+              "text": "CreateCaseProps"
+            },
             ") => React.ReactElement<",
-            "CreateCaseProps",
+            {
+              "pluginId": "cases",
+              "scope": "public",
+              "docId": "kibCasesPluginApi",
+              "section": "def-public.CreateCaseProps",
+              "text": "CreateCaseProps"
+            },
             ">"
           ],
           "source": {
             "path": "x-pack/plugins/cases/public/types.ts",
-            "lineNumber": 53
+            "lineNumber": 78
           },
           "deprecated": false,
-          "returnComment": [],
+          "returnComment": [
+            "A react component for creating a new case"
+          ],
           "children": [
             {
               "parentPluginId": "cases",
@@ -667,13 +1256,21 @@
               "type": "Object",
               "tags": [],
               "label": "props",
-              "description": [],
-              "signature": [
+              "description": [
                 "CreateCaseProps"
               ],
+              "signature": [
+                {
+                  "pluginId": "cases",
+                  "scope": "public",
+                  "docId": "kibCasesPluginApi",
+                  "section": "def-public.CreateCaseProps",
+                  "text": "CreateCaseProps"
+                }
+              ],
               "source": {
                 "path": "x-pack/plugins/cases/public/types.ts",
-                "lineNumber": 53
+                "lineNumber": 78
               },
               "deprecated": false
             }
@@ -685,20 +1282,36 @@
           "type": "Function",
           "tags": [],
           "label": "getRecentCases",
-          "description": [],
+          "description": [
+            "\nGet the recent cases component"
+          ],
           "signature": [
             "(props: ",
-            "RecentCasesProps",
+            {
+              "pluginId": "cases",
+              "scope": "public",
+              "docId": "kibCasesPluginApi",
+              "section": "def-public.RecentCasesProps",
+              "text": "RecentCasesProps"
+            },
             ") => React.ReactElement<",
-            "RecentCasesProps",
+            {
+              "pluginId": "cases",
+              "scope": "public",
+              "docId": "kibCasesPluginApi",
+              "section": "def-public.RecentCasesProps",
+              "text": "RecentCasesProps"
+            },
             ">"
           ],
           "source": {
             "path": "x-pack/plugins/cases/public/types.ts",
-            "lineNumber": 54
+            "lineNumber": 84
           },
           "deprecated": false,
-          "returnComment": [],
+          "returnComment": [
+            "A react component for showing recent cases"
+          ],
           "children": [
             {
               "parentPluginId": "cases",
@@ -706,13 +1319,21 @@
               "type": "Object",
               "tags": [],
               "label": "props",
-              "description": [],
-              "signature": [
+              "description": [
                 "RecentCasesProps"
               ],
+              "signature": [
+                {
+                  "pluginId": "cases",
+                  "scope": "public",
+                  "docId": "kibCasesPluginApi",
+                  "section": "def-public.RecentCasesProps",
+                  "text": "RecentCasesProps"
+                }
+              ],
               "source": {
                 "path": "x-pack/plugins/cases/public/types.ts",
-                "lineNumber": 54
+                "lineNumber": 84
               },
               "deprecated": false
             }
@@ -6138,7 +6759,7 @@
         "label": "Comment",
         "description": [],
         "signature": [
-          "({ comment: string; type: ",
+          "({ type: ",
           {
             "pluginId": "cases",
             "scope": "common",
@@ -6146,7 +6767,15 @@
             "section": "def-common.CommentType",
             "text": "CommentType"
           },
-          ".user; owner: string; } & { associationType: ",
+          ".alert | ",
+          {
+            "pluginId": "cases",
+            "scope": "common",
+            "docId": "kibCasesPluginApi",
+            "section": "def-common.CommentType",
+            "text": "CommentType"
+          },
+          ".generatedAlert; alertId: string | string[]; index: string | string[]; rule: { id: string | null; name: string | null; }; owner: string; } & { associationType: ",
           {
             "pluginId": "cases",
             "scope": "common",
@@ -6170,15 +6799,7 @@
             "section": "def-common.ElasticUser",
             "text": "ElasticUser"
           },
-          " | null; version: string; }) | ({ type: ",
-          {
-            "pluginId": "cases",
-            "scope": "common",
-            "docId": "kibCasesPluginApi",
-            "section": "def-common.CommentType",
-            "text": "CommentType"
-          },
-          ".alert | ",
+          " | null; version: string; }) | ({ comment: string; type: ",
           {
             "pluginId": "cases",
             "scope": "common",
@@ -6186,7 +6807,7 @@
             "section": "def-common.CommentType",
             "text": "CommentType"
           },
-          ".generatedAlert; alertId: string | string[]; index: string | string[]; rule: { id: string | null; name: string | null; }; owner: string; } & { associationType: ",
+          ".user; owner: string; } & { associationType: ",
           {
             "pluginId": "cases",
             "scope": "common",
@@ -6333,7 +6954,7 @@
         "label": "CommentPatchRequest",
         "description": [],
         "signature": [
-          "({ comment: string; type: ",
+          "({ type: ",
           {
             "pluginId": "cases",
             "scope": "common",
@@ -6341,7 +6962,7 @@
             "section": "def-common.CommentType",
             "text": "CommentType"
           },
-          ".user; owner: string; } & { id: string; version: string; }) | ({ type: ",
+          ".alert | ",
           {
             "pluginId": "cases",
             "scope": "common",
@@ -6349,7 +6970,7 @@
             "section": "def-common.CommentType",
             "text": "CommentType"
           },
-          ".alert | ",
+          ".generatedAlert; alertId: string | string[]; index: string | string[]; rule: { id: string | null; name: string | null; }; owner: string; } & { id: string; version: string; }) | ({ comment: string; type: ",
           {
             "pluginId": "cases",
             "scope": "common",
@@ -6357,7 +6978,7 @@
             "section": "def-common.CommentType",
             "text": "CommentType"
           },
-          ".generatedAlert; alertId: string | string[]; index: string | string[]; rule: { id: string | null; name: string | null; }; owner: string; } & { id: string; version: string; })"
+          ".user; owner: string; } & { id: string; version: string; })"
         ],
         "source": {
           "path": "x-pack/plugins/cases/common/api/cases/comment.ts",
@@ -6374,7 +6995,7 @@
         "label": "CommentRequest",
         "description": [],
         "signature": [
-          "{ comment: string; type: ",
+          "{ type: ",
           {
             "pluginId": "cases",
             "scope": "common",
@@ -6382,7 +7003,7 @@
             "section": "def-common.CommentType",
             "text": "CommentType"
           },
-          ".user; owner: string; } | { type: ",
+          ".alert | ",
           {
             "pluginId": "cases",
             "scope": "common",
@@ -6390,7 +7011,7 @@
             "section": "def-common.CommentType",
             "text": "CommentType"
           },
-          ".alert | ",
+          ".generatedAlert; alertId: string | string[]; index: string | string[]; rule: { id: string | null; name: string | null; }; owner: string; } | { comment: string; type: ",
           {
             "pluginId": "cases",
             "scope": "common",
@@ -6398,7 +7019,7 @@
             "section": "def-common.CommentType",
             "text": "CommentType"
           },
-          ".generatedAlert; alertId: string | string[]; index: string | string[]; rule: { id: string | null; name: string | null; }; owner: string; }"
+          ".user; owner: string; }"
         ],
         "source": {
           "path": "x-pack/plugins/cases/common/api/cases/comment.ts",
diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx
index 0f9cbe5364b63..00714b3217fca 100644
--- a/api_docs/cases.mdx
+++ b/api_docs/cases.mdx
@@ -32,9 +32,6 @@ import casesObj from './cases.json';
 ### Interfaces
 <DocDefinitionList data={casesObj.client.interfaces}/>
 
-### Consts, variables and types
-<DocDefinitionList data={casesObj.client.misc}/>
-
 ## Server
 
 ### Classes
diff --git a/api_docs/deprecations.mdx b/api_docs/deprecations.mdx
index d9261b943d170..74dae7faf838a 100644
--- a/api_docs/deprecations.mdx
+++ b/api_docs/deprecations.mdx
@@ -111,6 +111,8 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibSavedObjectsPluginApi" section="def-public.SavedObject" text="SavedObject"/> | [clone_panel_action.tsx#L14](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/actions/clone_panel_action.tsx#L14) | - |
 | <DocLink id="kibSavedObjectsPluginApi" section="def-public.SavedObject" text="SavedObject"/> | [clone_panel_action.tsx#L98](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/actions/clone_panel_action.tsx#L98) | - |
 | <DocLink id="kibSavedObjectsPluginApi" section="def-public.SavedObject" text="SavedObject"/> | [clone_panel_action.tsx#L126](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/actions/clone_panel_action.tsx#L126) | - |
+| <DocLink id="kibSavedObjectsPluginApi" section="def-public.SavedObject" text="SavedObject"/> | [use_dashboard_state_manager.ts#L23](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/hooks/use_dashboard_state_manager.ts#L23) | - |
+| <DocLink id="kibSavedObjectsPluginApi" section="def-public.SavedObject" text="SavedObject"/> | [use_dashboard_state_manager.ts#L35](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/hooks/use_dashboard_state_manager.ts#L35) | - |
 
 
 
@@ -127,8 +129,6 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [search_embeddable.ts#L23](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/search_embeddable.ts#L23) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [search_embeddable.ts#L59](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/search_embeddable.ts#L59) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [kibana_services.ts#L104](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/kibana_services.ts#L104) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [search_embeddable.ts#L23](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/search_embeddable.ts#L23) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [search_embeddable.ts#L59](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/search_embeddable.ts#L59) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [kibana_services.ts#L101](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/kibana_services.ts#L101) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [create_doc_table_react.tsx#L15](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/angular/doc_table/create_doc_table_react.tsx#L15) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [create_doc_table_react.tsx#L25](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/angular/doc_table/create_doc_table_react.tsx#L25) | - |
@@ -153,7 +153,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | Deprecated API | Reference location | Remove By |
 | ---------------|-----------|-----------|
 | <DocLink id="kibSavedObjectsPluginApi" section="def-public.SavedObjectSaveModal" text="SavedObjectSaveModal"/> | [attribute_service.tsx#L13](https://github.com/elastic/kibana/tree/master/src/plugins/embeddable/public/lib/attribute_service/attribute_service.tsx#L13) | - |
-| <DocLink id="kibSavedObjectsPluginApi" section="def-public.SavedObjectSaveModal" text="SavedObjectSaveModal"/> | [attribute_service.tsx#L165](https://github.com/elastic/kibana/tree/master/src/plugins/embeddable/public/lib/attribute_service/attribute_service.tsx#L165) | - |
+| <DocLink id="kibSavedObjectsPluginApi" section="def-public.SavedObjectSaveModal" text="SavedObjectSaveModal"/> | [attribute_service.tsx#L167](https://github.com/elastic/kibana/tree/master/src/plugins/embeddable/public/lib/attribute_service/attribute_service.tsx#L167) | - |
 
 
 
@@ -189,7 +189,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [query_bar.tsx#L30](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#L30) | - |
 | <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [query_bar.tsx#L38](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#L38) | - |
 | <DocLink id="kibCorePluginApi" section="def-server.AsyncPlugin" text="AsyncPlugin"/> | [plugin.ts#L14](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/server/plugin.ts#L14) | - |
-| <DocLink id="kibCorePluginApi" section="def-server.AsyncPlugin" text="AsyncPlugin"/> | [plugin.ts#L190](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/server/plugin.ts#L190) | - |
+| <DocLink id="kibCorePluginApi" section="def-server.AsyncPlugin" text="AsyncPlugin"/> | [plugin.ts#L189](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/server/plugin.ts#L189) | - |
 | <DocLink id="kibCorePluginApi" section="def-server.AsyncPlugin" text="AsyncPlugin"/> | [plugin.d.ts#L2](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/target/types/server/plugin.d.ts#L2) | - |
 | <DocLink id="kibCorePluginApi" section="def-server.AsyncPlugin" text="AsyncPlugin"/> | [plugin.d.ts#L84](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/target/types/server/plugin.d.ts#L84) | - |
 
@@ -228,18 +228,18 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 
 | Deprecated API | Reference location | Remove By |
 | ---------------|-----------|-----------|
-| <DocLink id="kibCorePluginApi" section="def-server.ILegacyCustomClusterClient" text="ILegacyCustomClusterClient"/> | [plugin.ts#L12](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/server/plugin.ts#L12) | 7.16 |
-| <DocLink id="kibCorePluginApi" section="def-server.ILegacyCustomClusterClient" text="ILegacyCustomClusterClient"/> | [plugin.ts#L38](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/server/plugin.ts#L38) | 7.16 |
+| <DocLink id="kibCorePluginApi" section="def-server.ILegacyCustomClusterClient" text="ILegacyCustomClusterClient"/> | [plugin.ts#L14](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/server/plugin.ts#L14) | 7.16 |
+| <DocLink id="kibCorePluginApi" section="def-server.ILegacyCustomClusterClient" text="ILegacyCustomClusterClient"/> | [plugin.ts#L42](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/server/plugin.ts#L42) | 7.16 |
 | <DocLink id="kibCorePluginApi" section="def-server.LegacyScopedClusterClient" text="LegacyScopedClusterClient"/> | [types.ts#L9](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/server/types.ts#L9) | 7.16 |
-| <DocLink id="kibCorePluginApi" section="def-server.LegacyScopedClusterClient" text="LegacyScopedClusterClient"/> | [types.ts#L39](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/server/types.ts#L39) | 7.16 |
+| <DocLink id="kibCorePluginApi" section="def-server.LegacyScopedClusterClient" text="LegacyScopedClusterClient"/> | [types.ts#L40](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/server/types.ts#L40) | 7.16 |
 | <DocLink id="kibCorePluginApi" section="def-server.LegacyScopedClusterClient" text="LegacyScopedClusterClient"/> | [types.d.ts#L1](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/target/types/server/types.d.ts#L1) | 7.16 |
-| <DocLink id="kibCorePluginApi" section="def-server.LegacyScopedClusterClient" text="LegacyScopedClusterClient"/> | [types.d.ts#L24](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/target/types/server/types.d.ts#L24) | 7.16 |
+| <DocLink id="kibCorePluginApi" section="def-server.LegacyScopedClusterClient" text="LegacyScopedClusterClient"/> | [types.d.ts#L25](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/target/types/server/types.d.ts#L25) | 7.16 |
 | <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [types.ts#L10](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/server/types.ts#L10) | 7.16 |
-| <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [types.ts#L42](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/server/types.ts#L42) | 7.16 |
-| <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [types.ts#L49](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/server/types.ts#L49) | 7.16 |
+| <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [types.ts#L43](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/server/types.ts#L43) | 7.16 |
+| <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [types.ts#L50](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/server/types.ts#L50) | 7.16 |
 | <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [types.d.ts#L1](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/target/types/server/types.d.ts#L1) | 7.16 |
-| <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [types.d.ts#L26](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/target/types/server/types.d.ts#L26) | 7.16 |
-| <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [types.d.ts#L32](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/target/types/server/types.d.ts#L32) | 7.16 |
+| <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [types.d.ts#L27](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/target/types/server/types.d.ts#L27) | 7.16 |
+| <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [types.d.ts#L33](https://github.com/elastic/kibana/tree/master/x-pack/plugins/index_management/target/types/server/types.d.ts#L33) | 7.16 |
 
 
 
@@ -578,6 +578,11 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [custom_metric_form.d.ts#L8](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/target/types/public/pages/metrics/inventory_view/components/waffle/metric_control/custom_metric_form.d.ts#L8) | - |
 | <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [index.d.ts#L1](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/target/types/public/pages/metrics/inventory_view/components/waffle/metric_control/index.d.ts#L1) | - |
 | <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [index.d.ts#L9](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/target/types/public/pages/metrics/inventory_view/components/waffle/metric_control/index.d.ts#L9) | - |
+| <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [log_entry_categories_analysis.ts#L9](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts#L9) | 7.16 |
+| <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [log_entry_categories_analysis.ts#L139](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts#L139) | 7.16 |
+| <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [log_entry_categories_analysis.ts#L405](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts#L405) | 7.16 |
+| <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [log_entry_categories_analysis.d.ts#L1](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/target/types/server/lib/log_analysis/log_entry_categories_analysis.d.ts#L1) | 7.16 |
+| <DocLink id="kibCorePluginApi" section="def-server.ILegacyScopedClusterClient" text="ILegacyScopedClusterClient"/> | [log_entry_categories_analysis.d.ts#L58](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/target/types/server/lib/log_analysis/log_entry_categories_analysis.d.ts#L58) | 7.16 |
 
 
 
@@ -587,8 +592,6 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | ---------------|-----------|-----------|
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [embeddable.tsx#L14](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx#L14) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [embeddable.tsx#L85](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx#L85) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [index.tsx#L25](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx#L25) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [index.tsx#L102](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx#L102) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [field_item.tsx#L47](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx#L47) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [field_item.tsx#L172](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx#L172) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [datapanel.tsx#L42](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx#L42) | - |
@@ -603,10 +606,10 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [types.ts#L8](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/types.ts#L8) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [types.ts#L57](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/types.ts#L57) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [field_stats.ts#L11](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L11) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [field_stats.ts#L141](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L141) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [field_stats.ts#L250](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L250) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [field_stats.ts#L290](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L290) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [field_stats.ts#L332](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L332) | - |
+| <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [field_stats.ts#L139](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L139) | - |
+| <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [field_stats.ts#L248](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L248) | - |
+| <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [field_stats.ts#L287](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L287) | - |
+| <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [field_stats.ts#L329](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L329) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [types.d.ts#L1](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/public/indexpattern_datasource/types.d.ts#L1) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [types.d.ts#L22](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/public/indexpattern_datasource/types.d.ts#L22) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [field_stats.d.ts#L3](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#L3) | - |
@@ -618,10 +621,10 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [types.ts#L8](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/types.ts#L8) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [types.ts#L57](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/types.ts#L57) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [field_stats.ts#L11](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L11) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [field_stats.ts#L141](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L141) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [field_stats.ts#L250](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L250) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [field_stats.ts#L290](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L290) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [field_stats.ts#L332](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L332) | - |
+| <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [field_stats.ts#L139](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L139) | - |
+| <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [field_stats.ts#L248](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L248) | - |
+| <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [field_stats.ts#L287](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L287) | - |
+| <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [field_stats.ts#L329](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L329) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [types.d.ts#L1](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/public/indexpattern_datasource/types.d.ts#L1) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [types.d.ts#L22](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/public/indexpattern_datasource/types.d.ts#L22) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [field_stats.d.ts#L3](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#L3) | - |
@@ -630,8 +633,6 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [field_stats.d.ts#L9](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#L9) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [embeddable.tsx#L14](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx#L14) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [embeddable.tsx#L85](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx#L85) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [index.tsx#L25](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx#L25) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [index.tsx#L102](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx#L102) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [field_item.tsx#L47](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx#L47) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [field_item.tsx#L172](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx#L172) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [datapanel.tsx#L42](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx#L42) | - |
@@ -646,10 +647,10 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [types.ts#L8](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/types.ts#L8) | - |
 | <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [types.ts#L57](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/types.ts#L57) | - |
 | <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [field_stats.ts#L11](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L11) | - |
-| <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [field_stats.ts#L141](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L141) | - |
-| <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [field_stats.ts#L250](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L250) | - |
-| <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [field_stats.ts#L290](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L290) | - |
-| <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [field_stats.ts#L332](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L332) | - |
+| <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [field_stats.ts#L139](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L139) | - |
+| <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [field_stats.ts#L248](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L248) | - |
+| <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [field_stats.ts#L287](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L287) | - |
+| <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [field_stats.ts#L329](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#L329) | - |
 | <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [types.d.ts#L1](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/public/indexpattern_datasource/types.d.ts#L1) | - |
 | <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [types.d.ts#L22](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/public/indexpattern_datasource/types.d.ts#L22) | - |
 | <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [field_stats.d.ts#L3](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#L3) | - |
@@ -935,7 +936,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | Deprecated API | Reference location | Remove By |
 | ---------------|-----------|-----------|
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [types.ts#L8](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#L8) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [types.ts#L44](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#L44) | - |
+| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [types.ts#L45](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#L45) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [es_doc_field.ts#L12](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/fields/es_doc_field.ts#L12) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [es_doc_field.ts#L45](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/fields/es_doc_field.ts#L45) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IFieldType" text="IFieldType"/> | [es_source.ts#L10](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts#L10) | - |
@@ -1125,7 +1126,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [get_docvalue_source_fields.test.ts#L10](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/get_docvalue_source_fields.test.ts#L10) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [get_docvalue_source_fields.test.ts#L12](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/get_docvalue_source_fields.test.ts#L12) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [types.ts#L8](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#L8) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [types.ts#L44](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#L44) | - |
+| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [types.ts#L45](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#L45) | - |
 | <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [es_doc_field.ts#L12](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/fields/es_doc_field.ts#L12) | - |
 | <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [es_doc_field.ts#L45](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/fields/es_doc_field.ts#L45) | - |
 | <DocLink id="kibDataPluginApi" section="def-server.IFieldType" text="IFieldType"/> | [es_source.ts#L10](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts#L10) | - |
@@ -1360,7 +1361,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibCorePluginApi" section="def-server.ILegacyCustomClusterClient" text="ILegacyCustomClusterClient"/> | [static_globals.ts#L43](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/server/static_globals.ts#L43) | 7.16 |
 | <DocLink id="kibCorePluginApi" section="def-server.ILegacyCustomClusterClient" text="ILegacyCustomClusterClient"/> | [plugin.ts#L18](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/server/plugin.ts#L18) | 7.16 |
 | <DocLink id="kibCorePluginApi" section="def-server.ILegacyCustomClusterClient" text="ILegacyCustomClusterClient"/> | [plugin.ts#L74](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/server/plugin.ts#L74) | 7.16 |
-| <DocLink id="kibCorePluginApi" section="def-server.ILegacyCustomClusterClient" text="ILegacyCustomClusterClient"/> | [plugin.ts#L284](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/server/plugin.ts#L284) | 7.16 |
+| <DocLink id="kibCorePluginApi" section="def-server.ILegacyCustomClusterClient" text="ILegacyCustomClusterClient"/> | [plugin.ts#L279](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/server/plugin.ts#L279) | 7.16 |
 | <DocLink id="kibCorePluginApi" section="def-server.ILegacyCustomClusterClient" text="ILegacyCustomClusterClient"/> | [types.d.ts#L2](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/target/types/server/types.d.ts#L2) | 7.16 |
 | <DocLink id="kibCorePluginApi" section="def-server.ILegacyCustomClusterClient" text="ILegacyCustomClusterClient"/> | [types.d.ts#L47](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/target/types/server/types.d.ts#L47) | 7.16 |
 | <DocLink id="kibCorePluginApi" section="def-server.ILegacyCustomClusterClient" text="ILegacyCustomClusterClient"/> | [plugin.d.ts#L1](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/target/types/server/plugin.d.ts#L1) | 7.16 |
@@ -1449,22 +1450,22 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 
 | Deprecated API | Reference location | Remove By |
 | ---------------|-----------|-----------|
-| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [types.ts#L19](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts#L19) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [types.ts#L104](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts#L104) | - |
+| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [types.ts#L18](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts#L18) | - |
+| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [types.ts#L95](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts#L95) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [utils.ts#L10](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts#L10) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [utils.ts#L53](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts#L53) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [utils.ts#L61](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts#L61) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [utils.ts#L69](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts#L69) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [default_configs.ts#L19](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/default_configs.ts#L19) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [default_configs.ts#L25](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/default_configs.ts#L25) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [types.ts#L19](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts#L19) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [types.ts#L104](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts#L104) | - |
+| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [default_configs.ts#L24](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/default_configs.ts#L24) | - |
+| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [types.ts#L18](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts#L18) | - |
+| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [types.ts#L95](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts#L95) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [utils.ts#L10](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts#L10) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [utils.ts#L53](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts#L53) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [utils.ts#L61](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts#L61) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [utils.ts#L69](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts#L69) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [default_configs.ts#L19](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/default_configs.ts#L19) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [default_configs.ts#L25](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/default_configs.ts#L25) | - |
+| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [default_configs.ts#L24](https://github.com/elastic/kibana/tree/master/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/default_configs.ts#L24) | - |
 
 
 
@@ -1540,9 +1541,9 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 
 | Deprecated API | Reference location | Remove By |
 | ---------------|-----------|-----------|
-| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [types.ts#L22](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#L22) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [types.ts#L72](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#L72) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [action.ts#L20](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts#L20) | - |
+| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [types.ts#L21](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#L21) | - |
+| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [types.ts#L66](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#L66) | - |
+| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [action.ts#L19](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts#L19) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [action.ts#L100](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts#L100) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [index.ts#L8](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#L8) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [index.ts#L86](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#L86) | - |
@@ -1579,9 +1580,9 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [types.ts#L41](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/network/pages/details/types.ts#L41) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [index.tsx#L12](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/network/components/network_top_countries_table/index.tsx#L12) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [index.tsx#L34](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/network/components/network_top_countries_table/index.tsx#L34) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [middleware.ts#L48](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#L48) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [middleware.ts#L64](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#L64) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [middleware.ts#L69](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#L69) | - |
+| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [middleware.ts#L44](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#L44) | - |
+| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [middleware.ts#L60](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#L60) | - |
+| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [middleware.ts#L65](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#L65) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [types.ts#L12](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/components/rules/description_step/types.ts#L12) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [types.ts#L28](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/components/rules/description_step/types.ts#L28) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [index.tsx#L15](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/components/rules/description_step/index.tsx#L15) | - |
@@ -1636,8 +1637,6 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [use_field_value_autocomplete.ts#L31](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/autocomplete/hooks/use_field_value_autocomplete.ts#L31) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [field_value_match.tsx#L19](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match.tsx#L19) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [field_value_match.tsx#L30](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match.tsx#L30) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [query.ts#L13](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/lib/detection_engine/reference_rules/query.ts#L13) | - |
-| <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [query.ts#L52](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/lib/detection_engine/reference_rules/query.ts#L52) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [model.ts#L8](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/sourcerer/model.ts#L8) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [model.ts#L30](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/sourcerer/model.ts#L30) | - |
 | <DocLink id="kibDataPluginApi" section="def-public.IIndexPattern" text="IIndexPattern"/> | [index.tsx#L33](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/components/rules/severity_mapping/index.tsx#L33) | - |
@@ -1754,9 +1753,9 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [index.tsx#L242](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/components/rules/risk_score_mapping/index.tsx#L242) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [index.tsx#L12](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/components/rules/autocomplete_field/index.tsx#L12) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IFieldType" text="IFieldType"/> | [index.tsx#L35](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/components/rules/autocomplete_field/index.tsx#L35) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [types.ts#L22](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#L22) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [types.ts#L72](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#L72) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [action.ts#L20](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts#L20) | - |
+| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [types.ts#L21](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#L21) | - |
+| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [types.ts#L66](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#L66) | - |
+| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [action.ts#L19](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts#L19) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [action.ts#L100](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts#L100) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [index.ts#L8](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#L8) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [index.ts#L86](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts#L86) | - |
@@ -1793,9 +1792,9 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [types.ts#L41](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/network/pages/details/types.ts#L41) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [index.tsx#L12](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/network/components/network_top_countries_table/index.tsx#L12) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [index.tsx#L34](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/network/components/network_top_countries_table/index.tsx#L34) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [middleware.ts#L48](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#L48) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [middleware.ts#L64](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#L64) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [middleware.ts#L69](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#L69) | - |
+| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [middleware.ts#L44](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#L44) | - |
+| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [middleware.ts#L60](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#L60) | - |
+| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [middleware.ts#L65](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#L65) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [types.ts#L12](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/components/rules/description_step/types.ts#L12) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [types.ts#L28](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/components/rules/description_step/types.ts#L28) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [index.tsx#L15](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/components/rules/description_step/index.tsx#L15) | - |
@@ -1850,8 +1849,6 @@ warning: This document is auto-generated and is meant to be viewed inside our ex
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [use_field_value_autocomplete.ts#L31](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/autocomplete/hooks/use_field_value_autocomplete.ts#L31) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [field_value_match.tsx#L19](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match.tsx#L19) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [field_value_match.tsx#L30](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match.tsx#L30) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [query.ts#L13](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/lib/detection_engine/reference_rules/query.ts#L13) | - |
-| <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [query.ts#L52](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/lib/detection_engine/reference_rules/query.ts#L52) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [model.ts#L8](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/sourcerer/model.ts#L8) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [model.ts#L30](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/sourcerer/model.ts#L30) | - |
 | <DocLink id="kibDataPluginApi" section="def-common.IIndexPattern" text="IIndexPattern"/> | [index.tsx#L33](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/components/rules/severity_mapping/index.tsx#L33) | - |
diff --git a/docs/api/alerting/list_rule_types.asciidoc b/docs/api/alerting/list_rule_types.asciidoc
index 98016c8cf82fa..31c8416e75059 100644
--- a/docs/api/alerting/list_rule_types.asciidoc
+++ b/docs/api/alerting/list_rule_types.asciidoc
@@ -8,7 +8,7 @@ Retrieve a list of alerting rule types that the user is authorized to access.
 
 Each rule type includes a list of consumer features. Within these features, users are authorized to perform either `read` or `all` operations on rules of that type. This helps determine which rule types users can read, but not create or modify.
 
-NOTE: Some rule types are limited to specific features.  These rule types are not available when <<defining-alerts, defining rules>> in <<management,Stack Management>>.
+NOTE: Some rule types are limited to specific features.  These rule types are not available when <<create-edit-rules, defining rules>> in <<management,Stack Management>>.
 
 [[list-rule-types-api-request]]
 ==== Request
diff --git a/docs/apm/apm-alerts.asciidoc b/docs/apm/apm-alerts.asciidoc
index b4afc2788895c..3e3e2b178ff10 100644
--- a/docs/apm/apm-alerts.asciidoc
+++ b/docs/apm/apm-alerts.asciidoc
@@ -15,7 +15,7 @@ and enables central management of all alerts from <<management,Kibana Management
 image::apm/images/apm-alert.png[Create an alert in the APM app]
 
 For a walkthrough of the alert flyout panel, including detailed information on each configurable property,
-see Kibana's <<defining-alerts,defining alerts>>.
+see Kibana's <<create-edit-rules,defining alerts>>.
 
 The APM app supports four different types of alerts:
 
@@ -126,4 +126,4 @@ See {kibana-ref}/alerting-getting-started.html[alerting and actions] for more in
 
 NOTE: If you are using an **on-premise** Elastic Stack deployment with security,
 communication between Elasticsearch and Kibana must have TLS configured.
-More information is in the alerting {kibana-ref}/alerting-getting-started.html#alerting-setup-prerequisites[prerequisites].
\ No newline at end of file
+More information is in the alerting {kibana-ref}/alerting-setup.html#alerting-prerequisites[prerequisites].
\ No newline at end of file
diff --git a/docs/canvas/canvas-function-reference.asciidoc b/docs/canvas/canvas-function-reference.asciidoc
index 67210c9d77057..272cd524c2c20 100644
--- a/docs/canvas/canvas-function-reference.asciidoc
+++ b/docs/canvas/canvas-function-reference.asciidoc
@@ -2893,6 +2893,33 @@ Alias: `type`
 [[u_fns]]
 == U
 
+[float]
+[[uiSetting_fn]]
+=== `uiSetting`
+
+Returns a UI settings parameter value.
+
+*Accepts:* `null`
+
+[cols="3*^<"]
+|===
+|Argument |Type |Description
+
+|_Unnamed_ ***
+
+Aliases: `parameter`
+|`string`
+|The parameter name.
+
+|`default`
+|`any`
+|A default value in case of the parameter is not set.
+
+Default: `null`
+|===
+
+*Returns:* `ui_setting`
+
 [float]
 [[urlparam_fn]]
 === `urlparam`
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md
index 449cc66cb3335..34de4f9e13cda 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md
@@ -23,7 +23,7 @@ export interface ExpressionFunctionDefinition<Name extends string, Input, Argume
 |  [help](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.help.md) | <code>string</code> | Help text displayed in the Expression editor. This text should be internationalized. |
 |  [inputTypes](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.inputtypes.md) | <code>Array&lt;TypeToString&lt;Input&gt;&gt;</code> | List of allowed type names for input value of this function. If this property is set the input of function will be cast to the first possible type in this list. If this property is missing the input will be provided to the function as-is. |
 |  [name](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.name.md) | <code>Name</code> | The name of the function, as will be used in expression. |
-|  [type](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.type.md) | <code>TypeToString&lt;UnwrapPromiseOrReturn&lt;Output&gt;&gt;</code> | Name of type of value this function outputs. |
+|  [type](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.type.md) | <code>TypeString&lt;Output&gt; &#124; UnmappedTypeStrings</code> | Name of type of value this function outputs. |
 
 ## Methods
 
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.type.md
index 4831f24a418bc..01ad35b8a1ba5 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.type.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.type.md
@@ -9,5 +9,5 @@ Name of type of value this function outputs.
 <b>Signature:</b>
 
 ```typescript
-type?: TypeToString<UnwrapPromiseOrReturn<Output>>;
+type?: TypeString<Output> | UnmappedTypeStrings;
 ```
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.md
index 6ba0f0feb82b3..9afd603bc4869 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.md
@@ -70,7 +70,7 @@ The actual function is defined in the <code>fn</code> key. The function can be \
 
 |  Method | Modifiers | Description |
 |  --- | --- | --- |
-|  [setup()](./kibana-plugin-plugins-expressions-public.expressionsservice.setup.md) |  | Returns Kibana Platform \*setup\* life-cycle contract. Useful to return the same contract on server-side and browser-side. |
-|  [start()](./kibana-plugin-plugins-expressions-public.expressionsservice.start.md) |  | Returns Kibana Platform \*start\* life-cycle contract. Useful to return the same contract on server-side and browser-side. |
+|  [setup(args)](./kibana-plugin-plugins-expressions-public.expressionsservice.setup.md) |  | Returns Kibana Platform \*setup\* life-cycle contract. Useful to return the same contract on server-side and browser-side. |
+|  [start(args)](./kibana-plugin-plugins-expressions-public.expressionsservice.start.md) |  | Returns Kibana Platform \*start\* life-cycle contract. Useful to return the same contract on server-side and browser-side. |
 |  [stop()](./kibana-plugin-plugins-expressions-public.expressionsservice.stop.md) |  |  |
 
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.setup.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.setup.md
index a51f3f073d518..991f1f717d5f5 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.setup.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.setup.md
@@ -9,8 +9,15 @@ Returns Kibana Platform \*setup\* life-cycle contract. Useful to return the same
 <b>Signature:</b>
 
 ```typescript
-setup(): ExpressionsServiceSetup;
+setup(...args: unknown[]): ExpressionsServiceSetup;
 ```
+
+## Parameters
+
+|  Parameter | Type | Description |
+|  --- | --- | --- |
+|  args | <code>unknown[]</code> |  |
+
 <b>Returns:</b>
 
 `ExpressionsServiceSetup`
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.start.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.start.md
index 766d703a0729d..34d33cacabebb 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.start.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.start.md
@@ -9,8 +9,15 @@ Returns Kibana Platform \*start\* life-cycle contract. Useful to return the same
 <b>Signature:</b>
 
 ```typescript
-start(): ExpressionsServiceStart;
+start(...args: unknown[]): ExpressionsServiceStart;
 ```
+
+## Parameters
+
+|  Parameter | Type | Description |
+|  --- | --- | --- |
+|  args | <code>unknown[]</code> |  |
+
 <b>Returns:</b>
 
 `ExpressionsServiceStart`
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md
index 51240f094b181..35248c01a4e29 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md
@@ -23,7 +23,7 @@ export interface ExpressionFunctionDefinition<Name extends string, Input, Argume
 |  [help](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.help.md) | <code>string</code> | Help text displayed in the Expression editor. This text should be internationalized. |
 |  [inputTypes](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.inputtypes.md) | <code>Array&lt;TypeToString&lt;Input&gt;&gt;</code> | List of allowed type names for input value of this function. If this property is set the input of function will be cast to the first possible type in this list. If this property is missing the input will be provided to the function as-is. |
 |  [name](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.name.md) | <code>Name</code> | The name of the function, as will be used in expression. |
-|  [type](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.type.md) | <code>TypeToString&lt;UnwrapPromiseOrReturn&lt;Output&gt;&gt;</code> | Name of type of value this function outputs. |
+|  [type](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.type.md) | <code>TypeString&lt;Output&gt; &#124; UnmappedTypeStrings</code> | Name of type of value this function outputs. |
 
 ## Methods
 
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.type.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.type.md
index a73ded342f053..2994b9547fd8c 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.type.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.type.md
@@ -9,5 +9,5 @@ Name of type of value this function outputs.
 <b>Signature:</b>
 
 ```typescript
-type?: TypeToString<UnwrapPromiseOrReturn<Output>>;
+type?: TypeString<Output> | UnmappedTypeStrings;
 ```
diff --git a/docs/management/connectors/action-types/index.asciidoc b/docs/management/connectors/action-types/index.asciidoc
index d3bd3d431748c..7868085ef9c96 100644
--- a/docs/management/connectors/action-types/index.asciidoc
+++ b/docs/management/connectors/action-types/index.asciidoc
@@ -119,7 +119,7 @@ When creating a new rule, add an <<index-action-type, Index action>> and select
 [role="screenshot"]
 image::images/pre-configured-alert-history-connector.png[Select pre-configured alert history connectors]
 
-Documents are indexed using a preconfigured schema that captures the <<defining-alerts-actions-variables, action variables>> available for the rule. By default, these documents are indexed into the `kibana-alert-history-default` index, but you can specify a different index. Index names must start with `kibana-alert-history-` to take advantage of the preconfigured alert history index template.
+Documents are indexed using a preconfigured schema that captures the <<defining-rules-actions-variables, action variables>> available for the rule. By default, these documents are indexed into the `kibana-alert-history-default` index, but you can specify a different index. Index names must start with `kibana-alert-history-` to take advantage of the preconfigured alert history index template.
 
 [IMPORTANT]
 ==============================================
diff --git a/docs/management/connectors/action-types/webhook.asciidoc b/docs/management/connectors/action-types/webhook.asciidoc
index aa52e8a3bdb43..02c3de139e0d5 100644
--- a/docs/management/connectors/action-types/webhook.asciidoc
+++ b/docs/management/connectors/action-types/webhook.asciidoc
@@ -91,4 +91,4 @@ Body::      A JSON payload sent to the request URL. For example:
 
 Mustache template variables (the text enclosed in double braces, for example, `context.rule.name`) have
 their values escaped, so that the final JSON will be valid (escaping double quote characters).
-For more information on Mustache template variables, refer to <<defining-alerts-actions-details>>.
+For more information on Mustache template variables, refer to <<defining-rules-actions-details>>.
diff --git a/docs/rule-type-template.asciidoc b/docs/rule-type-template.asciidoc
index 605bdd57c1492..5fe4de81bcddc 100644
--- a/docs/rule-type-template.asciidoc
+++ b/docs/rule-type-template.asciidoc
@@ -6,7 +6,7 @@ Include a short description of the rule type.
 [float]
 ==== Create the rule
 
-Fill in the <<defining-alerts-general-details, rule details>>, then select *<RULE TYPE>*.
+Fill in the <<defining-rules-general-details, rule details>>, then select *<RULE TYPE>*.
 
 [float]
 ==== Define the conditions
@@ -25,7 +25,7 @@ Condition2:: This is another condition the user must define.
 [float]
 ==== Add action variables
 
-<<defining-alerts-actions-details, Add an action>> to run when the rule condition is met. The following variables are specific to the <RULE TYPE> rule. You can also specify <<defining-alerts-actions-variables, variables common to all rules>>.
+<<defining-rules-actions-details, Add an action>> to run when the rule condition is met. The following variables are specific to the <RULE TYPE> rule. You can also specify <<defining-rules-actions-variables, variables common to all rules>>.
 
 `context.variableA`:: A short description of the context variable defined by the rule type.
 `context.variableB`:: A short description of the context variable defined by the rule type with an example. Example: `this is what variableB outputs`.
diff --git a/docs/user/alerting/alerting-getting-started.asciidoc b/docs/user/alerting/alerting-getting-started.asciidoc
index bb11d2a0be423..8c17f8ec93b96 100644
--- a/docs/user/alerting/alerting-getting-started.asciidoc
+++ b/docs/user/alerting/alerting-getting-started.asciidoc
@@ -11,7 +11,7 @@ image::images/alerting-overview.png[Rules and Connectors UI]
 
 [IMPORTANT]
 ==============================================
-To make sure you can access alerting and actions, see the <<alerting-setup-prerequisites, setup and pre-requisites>> section.
+To make sure you can access alerting and actions, see the <<alerting-prerequisites, setup and pre-requisites>> section.
 ==============================================
 
 [float]
@@ -22,7 +22,7 @@ Actions typically involve interaction with {kib} services or third party integra
 This section describes all of these elements and how they operate together.
 
 [float]
-=== What is a rule?
+=== Rules
 
 A rule specifies a background task that runs on the {kib} server to check for specific conditions. It consists of three main parts: 
 
@@ -30,7 +30,10 @@ A rule specifies a background task that runs on the {kib} server to check for sp
 * *Schedule*: when/how often should detection checks run?
 * *Actions*: what happens when a condition is detected?
 
-For example, when monitoring a set of servers, a rule might check for average CPU usage > 0.9 on each server for the last two minutes (condition), checked every minute (schedule), sending a warning email message via SMTP with subject `CPU on {{server}} is high` (action).
+For example, when monitoring a set of servers, a rule might: 
+* Check for average CPU usage > 0.9 on each server for the last two minutes (condition).
+* Check every minute (schedule).
+* Send a warning email message via SMTP with subject `CPU on {{server}} is high` (action).
 
 image::images/what-is-a-rule.svg[Three components of a rule]
 
@@ -40,7 +43,7 @@ The following sections describe each part of the rule in more detail.
 [[alerting-concepts-conditions]]
 ==== Conditions
 
-Under the hood, {kib} rules detect conditions by running a javascript function on the {kib} server, which gives it the flexibility to support a wide range of conditions, anything from the results of a simple {es} query to heavy computations involving data from multiple sources or external systems. 
+Under the hood, {kib} rules detect conditions by running a Javascript function on the {kib} server, which gives it the flexibility to support a wide range of conditions, anything from the results of a simple {es} query to heavy computations involving data from multiple sources or external systems. 
 
 These conditions are packaged and exposed as *rule types*. A rule type hides the underlying details of the condition, and exposes a set of parameters
 to control the details of the conditions to detect.
@@ -68,22 +71,22 @@ Actions are invocations of connectors, which allow interaction with {kib} servic
 
 When defining actions in a rule, you specify:
 
-* the *connector type*: the type of service or integration to use
-* the connection for that type by referencing a <<alerting-concepts-connectors, connector>>
-* a mapping of rule values to properties exposed for that type of action
+* The *connector type*: the type of service or integration to use
+* The connection for that type by referencing a <<alerting-concepts-connectors, connector>>
+* A mapping of rule values to properties exposed for that type of action
 
 The result is a template: all the parameters needed to invoke a service are supplied except for specific values that are only known at the time the rule condition is detected. 
 
 In the server monitoring example, the `email` connector type is used, and `server` is mapped to the body of the email, using the template string `CPU on {{server}} is high`.
 
-When the rule detects the condition, it creates an <<alerting-concepts-alert-instances, alert>> containing the details of the condition, renders the template with these details such as server name, and executes the action on the {kib} server by invoking the `email` connector type. 
+When the rule detects the condition, it creates an <<alerting-concepts-alerts, alert>> containing the details of the condition, renders the template with these details such as server name, and executes the action on the {kib} server by invoking the `email` connector type. 
 
 image::images/what-is-an-action.svg[Actions are like templates that are rendered when an alert detects a condition]
 
 See <<action-types>> for details on the types of connectors provided by {kib}.
 
 [float]
-[[alerting-concepts-alert-instances]]
+[[alerting-concepts-alerts]]
 === Alerts
 
 When checking for a condition, a rule might identify multiple occurrences of the condition. {kib} tracks each of these *alerts* separately and takes an action per alert.
@@ -92,22 +95,6 @@ Using the server monitoring example, each server with average CPU > 0.9 is track
 
 image::images/alerts.svg[{kib} tracks each detected condition as an alert and takes action on each alert]
 
-[float]
-[[alerting-concepts-suppressing-duplicate-notifications]]
-=== Suppressing duplicate notifications
-
-Since actions are executed per alert, a rule can end up generating a large number of actions. Take the following example where a rule is monitoring three servers every minute for CPU usage > 0.9:
-
-* Minute 1: server X123 > 0.9. *One email* is sent for server X123.
-* Minute 2: X123 and Y456 > 0.9. *Two emails* are sent, one for X123 and one for Y456.
-* Minute 3: X123, Y456, Z789 > 0.9. *Three emails* are sent, one for each of X123, Y456, Z789.
-
-In the above example, three emails are sent for server X123 in the span of 3 minutes for the same rule. Often it's desirable to suppress frequent re-notification. Operations like muting and throttling can be applied at the alert level. If we set the rule re-notify interval to 5 minutes, we reduce noise by only getting emails for new servers that exceed the threshold:
-
-* Minute 1: server X123 > 0.9. *One email* is sent for server X123.
-* Minute 2: X123 and Y456 > 0.9. *One email* is sent for Y456.
-* Minute 3: X123, Y456, Z789 > 0.9. *One email* is sent for Z789.
-
 [float]
 [[alerting-concepts-connectors]]
 === Connectors
@@ -120,7 +107,7 @@ Rather than repeatedly entering connection information and credentials for each
 image::images/rule-concepts-connectors.svg[Connectors provide a central place to store service connection settings]
 
 [float]
-=== Summary
+== Putting it all together
 
 A *rule* consists of conditions, *actions*, and a schedule. When conditions are met, *alerts* are created that render *actions* and invoke them. To make action setup and update easier, actions use *connectors* that centralize the information used to connect with {kib} services and third-party integrations. The following example ties these concepts together:
 
@@ -131,7 +118,6 @@ image::images/rule-concepts-summary.svg[Rules, connectors, alerts and actions wo
 . {kib} invokes the actions, sending them to a third party *integration* like an email service.
 . If the third party integration has connection parameters or credentials, {kib} will fetch these from the *connector* referenced in the action.
 
-
 [float]
 [[alerting-concepts-differences]]
 == Differences from Watcher
@@ -152,63 +138,7 @@ Pre-packaged *rule types* simplify setup and hide the details of complex, domain
 
 [float]
 [[alerting-setup-prerequisites]]
-== Setup and prerequisites
-
-If you are using an *on-premises* Elastic Stack deployment:
-
-* In the kibana.yml configuration file, add the <<general-alert-action-settings,`xpack.encryptedSavedObjects.encryptionKey`>> setting.
-* For emails to have a footer with a link back to {kib}, set the <<server-publicBaseUrl, `server.publicBaseUrl`>> configuration setting.
-
-If you are using an *on-premises* Elastic Stack deployment with <<using-kibana-with-security, *security*>>:
-
-* You must enable Transport Layer Security (TLS) for communication <<configuring-tls-kib-es, between {es} and {kib}>>. {kib} alerting uses <<api-keys, API keys>> to secure background rule checks and actions, and API keys require {ref}/configuring-tls.html#tls-http[TLS on the HTTP interface]. A proxy will not suffice.
-
-[float]
-[[alerting-setup-production]]
-== Production considerations and scaling guidance
-
-When relying on alerting and actions as mission critical services, make sure you follow the <<alerting-production-considerations,Alerting production considerations>>.
-
-See <<alerting-scaling-guidance>> for more information on the scalability of {kib} alerting.
-
-[float]
-[[alerting-security]]
-== Security
+== Prerequisites
+<<alerting-prerequisites, Alerting prerequisites>> 
 
-To access alerting in a space, a user must have access to one of the following features:
-
-* Alerting
-* <<xpack-apm,*APM*>>
-* <<logs-app,*Logs*>>
-* <<xpack-ml,*{ml-cap}*>>
-* <<metrics-app,*Metrics*>>
-* <<xpack-siem,*Security*>>
-* <<uptime-app,*Uptime*>>
-
-See <<kibana-feature-privileges, feature privileges>> for more information on configuring roles that provide access to these features.
-Also note that a user will need +read+ privileges for the *Actions and Connectors* feature to attach actions to a rule or to edit a rule that has an action attached to it.
-
-[float]
-[[alerting-spaces]]
-=== Space isolation
-
-Rules and connectors are isolated to the {kib} space in which they were created. A rule or connector created in one space will not be visible in another. 
-
-[float]
-[[alerting-authorization]]
-=== Authorization
-
-Rules, including all background detection and the actions they generate are authorized using an <<api-keys, API key>> associated with the last user to edit the rule. Upon creating or modifying a rule, an API key is generated for that user, capturing a snapshot of their privileges at that moment in time. The API key is then used to run all background tasks associated with the rule including detection checks and executing actions. 
-
-[IMPORTANT]
-==============================================
-If a rule requires certain privileges to run, such as index privileges, keep in mind that if a user without those privileges updates the rule, the rule will no longer function.  
-==============================================
-
-[float]
-[[alerting-restricting-actions]]
-=== Restricting actions
-
-For security reasons you may wish to limit the extent to which {kib} can connect to external services. <<action-settings>> allows you to disable certain <<action-types>> and allowlist the hostnames that {kib} can connect with.
-
---
+--
\ No newline at end of file
diff --git a/docs/user/alerting/alerting-setup.asciidoc b/docs/user/alerting/alerting-setup.asciidoc
new file mode 100644
index 0000000000000..39f1af0030e0a
--- /dev/null
+++ b/docs/user/alerting/alerting-setup.asciidoc
@@ -0,0 +1,68 @@
+[role="xpack"]
+[[alerting-setup]]
+== Alerting Setup
+++++
+<titleabbrev>Setup</titleabbrev>
+++++
+
+The Alerting feature is automatically enabled in {kib}, but might require some additional configuration.
+
+[float]
+[[alerting-prerequisites]]
+=== Prerequisites
+If you are using an *on-premises* Elastic Stack deployment:
+
+* In the kibana.yml configuration file, add the <<general-alert-action-settings,`xpack.encryptedSavedObjects.encryptionKey`>> setting.
+* For emails to have a footer with a link back to {kib}, set the <<server-publicBaseUrl, `server.publicBaseUrl`>> configuration setting.
+
+If you are using an *on-premises* Elastic Stack deployment with <<using-kibana-with-security, *security*>>:
+
+* You must enable Transport Layer Security (TLS) for communication <<configuring-tls-kib-es, between {es} and {kib}>>. {kib} alerting uses <<api-keys, API keys>> to secure background rule checks and actions, and API keys require {ref}/configuring-tls.html#tls-http[TLS on the HTTP interface]. A proxy will not suffice.
+
+[float]
+[[alerting-setup-production]]
+=== Production considerations and scaling guidance
+
+When relying on alerting and actions as mission critical services, make sure you follow the <<alerting-production-considerations,Alerting production considerations>>.
+
+See <<alerting-scaling-guidance>> for more information on the scalability of {kib} alerting.
+
+[float]
+[[alerting-security]]
+=== Security
+
+To access alerting in a space, a user must have access to one of the following features:
+
+* Alerting
+* <<xpack-apm,*APM*>>
+* <<logs-app,*Logs*>>
+* <<xpack-ml,*{ml-cap}*>>
+* <<metrics-app,*Metrics*>>
+* <<xpack-siem,*Security*>>
+* <<uptime-app,*Uptime*>>
+
+See <<kibana-feature-privileges, feature privileges>> for more information on configuring roles that provide access to these features.
+Also note that a user will need +read+ privileges for the *Actions and Connectors* feature to attach actions to a rule or to edit a rule that has an action attached to it.
+
+[float]
+[[alerting-restricting-actions]]
+==== Restrict actions
+
+For security reasons you may wish to limit the extent to which {kib} can connect to external services. <<action-settings>> allows you to disable certain <<action-types>> and allowlist the hostnames that {kib} can connect with.
+
+[float]
+[[alerting-spaces]]
+=== Space isolation
+
+Rules and connectors are isolated to the {kib} space in which they were created. A rule or connector created in one space will not be visible in another. 
+
+[float]
+[[alerting-authorization]]
+=== Authorization
+
+Rules, including all background detection and the actions they generate are authorized using an <<api-keys, API key>> associated with the last user to edit the rule. Upon creating or modifying a rule, an API key is generated for that user, capturing a snapshot of their privileges at that moment in time. The API key is then used to run all background tasks associated with the rule including detection checks and executing actions. 
+
+[IMPORTANT]
+==============================================
+If a rule requires certain privileges to run, such as index privileges, keep in mind that if a user without those privileges updates the rule, the rule will no longer function.  
+==============================================
diff --git a/docs/user/alerting/alerting-troubleshooting.asciidoc b/docs/user/alerting/alerting-troubleshooting.asciidoc
index b7fd98d1c674e..b7b0c749dfe14 100644
--- a/docs/user/alerting/alerting-troubleshooting.asciidoc
+++ b/docs/user/alerting/alerting-troubleshooting.asciidoc
@@ -1,6 +1,9 @@
 [role="xpack"]
 [[alerting-troubleshooting]]
 == Alerting Troubleshooting
+++++
+<titleabbrev>Troubleshooting</titleabbrev>
+++++
 
 This page describes how to resolve common problems you might encounter with Alerting.
 If your problem isn’t described here, please review open issues in the following GitHub repositories:
diff --git a/docs/user/alerting/create-and-manage-rules.asciidoc b/docs/user/alerting/create-and-manage-rules.asciidoc
new file mode 100644
index 0000000000000..af6714aef662f
--- /dev/null
+++ b/docs/user/alerting/create-and-manage-rules.asciidoc
@@ -0,0 +1,184 @@
+[role="xpack"]
+[[create-and-manage-rules]]
+== Create and manage rules
+
+The *Rules* UI provides a cross-app view of alerting. Different {kib} apps like {observability-guide}/create-alerts.html[*Observability*], {security-guide}/prebuilt-rules.html[*Security*], <<geo-alerting, *Maps*>> and <<xpack-ml, *Machine Learning*>> can offer their own rules. The *Rules* UI provides a central place to:
+
+* <<create-edit-rules, Create and edit>> rules
+* <<controlling-rules, Manage rules>> including enabling/disabling, muting/unmuting, and deleting
+* Drill-down to <<rule-details, rule details>>
+
+[role="screenshot"]
+image:images/rules-and-connectors-ui.png[Example rule listing in the Rules and Connectors UI]
+
+For more information on alerting concepts and the types of rules and connectors available, see <<alerting-getting-started>>.
+
+[float]
+=== Required permissions
+
+Access to rules is granted based on your privileges to alerting-enabled features. See <<alerting-security, Alerting Security>> for more information.
+
+[float]
+[[create-edit-rules]]
+=== Create and edit rules
+
+Many rules must be created within the context of a {kib} app like <<metrics-app, Metrics>>, <<xpack-apm, APM>>, or <<uptime-app, Uptime>>, but others are generic. Generic rule types can be created in the *Rules* management UI by clicking the *Create* button. This will launch a flyout that guides you through selecting a rule type and configuring its conditions and action type. Refer to <<stack-rules, Stack rules>> for details on what types of rules are available and how to configure them.
+
+After a rule is created, you can re-open the flyout and change a rule's properties by clicking the *Edit* button shown on each row of the rule listing.
+
+[float]
+[[defining-rules-general-details]]
+==== General rule details
+
+All rules share the following four properties.
+
+Name::      The name of the rule. While this name does not have to be unique, the name can be referenced in actions and also appears in the searchable rule listing in the *Management* UI. A distinctive name can help identify and find a rule.
+Tags::      A list of tag names that can be applied to a rule. Tags can help you organize and find rules, because tags appear in the rule listing in the *Management* UI, which is searchable by tag.
+Check every::      This value determines how frequently the rule conditions are checked. Note that the timing of background rule checks is not guaranteed, particularly for intervals of less than 10 seconds. See <<alerting-production-considerations, Alerting production considerations>> for more information.
+Notify::      This value limits how often actions are repeated when an alert remains active across rule checks. See <<alerting-concepts-suppressing-duplicate-notifications>> for more information. +
+- **Only on status change**: Actions are not repeated when an alert remains active across checks. Actions run only when the alert status changes.
+- **Every time alert is active**: Actions are repeated when an alert remains active across checks.
+- **On a custom action interval**: Actions are suppressed for the throttle interval, but repeat when an alert remains active across checks for a duration longer than the throttle interval.
+
+[float]
+[[alerting-concepts-suppressing-duplicate-notifications]]
+[NOTE]
+==============================================
+Since actions are executed per alert, a rule can end up generating a large number of actions. Take the following example where a rule is monitoring three servers every minute for CPU usage > 0.9, and the rule is set to notify **Every time alert is active**:
+
+* Minute 1: server X123 > 0.9. *One email* is sent for server X123.
+* Minute 2: X123 and Y456 > 0.9. *Two emails* are sent, one for X123 and one for Y456.
+* Minute 3: X123, Y456, Z789 > 0.9. *Three emails* are sent, one for each of X123, Y456, Z789.
+
+In the above example, three emails are sent for server X123 in the span of 3 minutes for the same rule. Often, it's desirable to suppress these re-notifications. If you set the rule **Notify** setting to **On a custom action interval** with an interval of 5 minutes, you reduce noise by only getting emails every 5 minutes for servers that continue to exceed the threshold:
+
+* Minute 1: server X123 > 0.9. *One email* is sent for server X123.
+* Minute 2: X123 and Y456 > 0.9. *One email* is sent for Y456.
+* Minute 3: X123, Y456, Z789 > 0.9. *One email* is sent for Z789.
+
+To get notified **only once** when a server exceeds the threshold, you can set the rule's **Notify** setting to **Only on status change**. 
+==============================================
+
+[role="screenshot"]
+image::images/rule-flyout-general-details.png[alt='All rules have name, tags, check every, and notify properties in common']
+
+[float]
+[[defining-rules-type-conditions]]
+==== Rule type and conditions
+
+Depending upon the {kib} app and context, you might be prompted to choose the type of rule to create. Some apps will pre-select the type of rule for you.
+
+[role="screenshot"]
+image::images/rule-flyout-rule-type-selection.png[Choosing the type of rule to create]
+
+Each rule type provides its own way of defining the conditions to detect, but an expression formed by a series of clauses is a common pattern. Each clause has a UI control that allows you to define the clause. For example, in an index threshold rule, the `WHEN` clause allows you to select an aggregation operation to apply to a numeric field.
+
+[role="screenshot"]
+image::images/rule-flyout-rule-conditions.png[UI for defining rule conditions on an index threshold rule]
+
+[float]
+[[defining-rules-actions-details]]
+==== Action type and details
+
+To receive notifications when a rule meets the defined conditions, you must add one or more actions. Start by selecting a type of connector for your action:
+
+[role="screenshot"]
+image::images/rule-flyout-connector-type-selection.png[UI for selecting an action type]
+
+Each action must specify a <<alerting-concepts-connectors, connector>> instance. If no connectors exist for the selected type, click **Add connector** to create one.
+
+[role="screenshot"]
+image::images/rule-flyout-action-no-connector.png[UI for adding connector]
+
+Once you have selected a connector, use the **Run When** dropdown to choose the action group to associate with this action. When a rule meets the defined condition, it is marked as **Active** and alerts are created and assigned to an action group. In addition to the action groups defined by the selected rule type, each rule also has a **Recovered** action group that is assigned when a rule's conditions are no longer detected.
+
+Each action type exposes different properties. For example, an email action allows you to set the recipients, the subject, and a message body in markdown format. See <<action-types>> for details on the types of actions provided by {kib} and their properties.
+
+[role="screenshot"]
+image::images/rule-flyout-action-details.png[UI for defining an email action]
+
+[float]
+[[defining-rules-actions-variables]]
+===== Action variables
+Using the https://mustache.github.io/[Mustache] template syntax `{{variable name}}`, you can pass rule values at the time a condition is detected to an action. You can access the list of available variables using the "add variable" button. Although available variables differ by rule type, all rule types pass the following variables:
+
+`rule.id`:: The ID of the rule.
+`rule.name`:: The name of the rule.
+`rule.spaceId`:: The ID of the space for the rule.
+`rule.tags`:: The list of tags applied to the rule.
+`date`:: The date the rule scheduled the action, in ISO format.
+`alert.id`:: The ID of the alert that scheduled the action.
+`alert.actionGroup`:: The ID of the action group of the alert that scheduled the action.
+`alert.actionSubgroup`:: The action subgroup of the alert that scheduled the action.
+`alert.actionGroupName`:: The name of the action group of the alert that scheduled the action.
+`kibanaBaseUrl`:: The configured <<server-publicBaseUrl, `server.publicBaseUrl`>>. If not configured, this will be empty.
+
+[role="screenshot"]
+image::images/rule-flyout-action-variables.png[Passing rule values to an action]
+
+Some cases exist where the variable values will be "escaped", when used in a context where escaping is needed:
+
+- For the <<email-action-type, Email>> connector, the `message` action configuration property escapes any characters that would be interpreted as Markdown.
+- For the <<slack-action-type, Slack>> connector, the `message` action configuration property escapes any characters that would be interpreted as Slack Markdown.
+- For the <<webhook-action-type, Webhook>> connector, the `body` action configuration property escapes any characters that are invalid in JSON string values.
+
+Mustache also supports "triple braces" of the form `{{{variable name}}}`, which indicates no escaping should be done at all.  Care should be used when using this form, as it could end up rendering the variable content in such a way as to make the resulting parameter invalid or formatted incorrectly.
+
+Each rule type defines additional variables as properties of the variable `context`.  For example, if a rule type defines a variable `value`, it can be used in an action parameter as `{{context.value}}`.  
+
+For diagnostic or exploratory purposes, action variables whose values are objects, such as `context`, can be referenced directly as variables.  The resulting value will be a JSON representation of the object.  For example, if an action parameter includes `{{context}}`, it will expand to the JSON representation of all the variables and values provided by the rule type.
+
+You can attach more than one action. Clicking the "Add action" button will prompt you to select another rule type and repeat the above steps again.
+
+[role="screenshot"]
+image::images/rule-flyout-add-action.png[You can add multiple actions on a rule]
+
+[NOTE]
+==============================================
+Actions are not required on rules. You can run a rule without actions to understand its behavior, and then <<action-settings, configure actions>> later.
+==============================================
+
+[float]
+[[controlling-rules]]
+=== Mute and disable rules
+
+The rule listing allows you to quickly mute/unmute, disable/enable, and delete individual rules by clicking menu button to open the actions menu. Muting means that the rule checks continue to run on a schedule, but that alert will not trigger any action.
+
+[role="screenshot"]
+image:images/individual-mute-disable.png[The actions button allows an individual rule to be muted, disabled, or deleted]
+
+You can perform these operations in bulk by multi-selecting rules, and then clicking the *Manage rules* button:
+
+[role="screenshot"]
+image:images/bulk-mute-disable.png[The Manage rules button lets you mute/unmute, enable/disable, and delete in bulk,width=75%]
+
+[float]
+[[rule-details]]
+=== Drilldown to rule details
+
+Select a rule name from the rule listing to access the *Rule details* page, which tells you about the state of the rule and provides granular control over the actions it is taking. 
+
+[role="screenshot"]
+image::images/rule-details-alerts-active.png[Rule details page with three alerts]
+
+In this example, the rule detects when a site serves more than a threshold number of bytes in a 24 hour period. Three sites are above the threshold. These are called alerts - occurrences of the condition being detected - and the alert name, status, time of detection, and duration of the condition are shown in this view.
+
+Upon detection, each alert can trigger one or more actions. If the condition persists, the same actions will trigger either on the next scheduled rule check, or (if defined) after the re-notify period on the rule has passed. To prevent re-notification, you can suppress future actions by clicking on the switch to mute an individual alert.
+
+[role="screenshot"]
+image::images/rule-details-alert-muting.png[Muting an alert,width=50%]
+
+Alerts will come and go from the list depending on whether they meet the rule conditions or not - unless they are muted. If a muted instance no longer meets the rule conditions, it will appear as inactive in the list. This prevents an alert from triggering actions if it reappears in the future.
+
+[role="screenshot"]
+image::images/rule-details-alerts-inactive.png[Rule details page with three inactive alerts]
+
+If you want to suppress actions on all current and future alerts, you can mute the entire rule. Rule checks continue to run and the alert list will update as alerts activate or deactivate, but no actions will be triggered.
+
+[role="screenshot"]
+image::images/rule-details-muting.png[Use the mute toggle to suppress all actions on current and future alerts,width=50%]
+
+You can also disable a rule altogether. When disabled, the rule stops running checks altogether and will clear any alerts it is tracking. You may want to disable rules that are not currently needed to reduce the load on {kib} and {es}.
+
+[role="screenshot"]
+image::images/rule-details-disabling.png[Use the disable toggle to turn off rule checks and clear alerts tracked]
diff --git a/docs/user/alerting/defining-rules.asciidoc b/docs/user/alerting/defining-rules.asciidoc
index 05885f1af13ba..686a7bbc8a37b 100644
--- a/docs/user/alerting/defining-rules.asciidoc
+++ b/docs/user/alerting/defining-rules.asciidoc
@@ -2,114 +2,10 @@
 [[defining-alerts]]
 == Defining rules
 
-{kib} alerting rules can be created in a variety of apps including <<xpack-apm,*APM*>>, <<xpack-ml,*{ml-app}*>>, <<metrics-app,*Metrics*>>, <<xpack-siem,*Security*>>, <<uptime-app,*Uptime*>> and from the <<management,*Management*>> UI. While alerting details may differ from app to app, they share a common interface for defining and configuring rules that this section describes in more detail.
-
-[float]
-=== Create a rule
-
-When you create a rule, you must define the rule details, conditions, and actions.
-
-. <<defining-alerts-general-details, General rule details>>
-. <<defining-alerts-type-conditions, Rule type and conditions>>
-. <<defining-alerts-actions-details, Action type and action details>>
-
-image::images/rule-flyout-sections.png[The three sections of a rule definition]
+This content has been moved to <<create-and-manage-rules>>.
 
 [float]
 [[defining-alerts-general-details]]
-=== General rule details
-
-All rules share the following four properties.
-
-[role="screenshot"]
-image::images/rule-flyout-general-details.png[alt='All rules have name, tags, check every, and notify properties in common']
-
-Name::      The name of the rule. While this name does not have to be unique, the name can be referenced in actions and also appears in the searchable rule listing in the management UI. A distinctive name can help identify and find a rule.
-Tags::      A list of tag names that can be applied to a rule. Tags can help you organize and find rules, because tags appear in the rule listing in the management UI which is searchable by tag.
-Check every::      This value determines how frequently the rule conditions below are checked. Note that the timing of background rule checks are not guaranteed, particularly for intervals of less than 10 seconds. See <<alerting-production-considerations, Alerting production considerations>> for more information.
-Notify::      This value limits how often actions are repeated when an alert remains active across rule checks. See <<alerting-concepts-suppressing-duplicate-notifications>> for more information. +
-- **Only on status change**: Actions are not repeated when an alert remains active across checks. Actions run only when the alert status changes.
-- **Every time alert is active**: Actions are repeated when an alert remains active across checks.
-- **On a custom action interval**: Actions are suppressed for the throttle interval, but repeat when an alert remains active across checks for a duration longer than the throttle interval.
-
-
-[float]
-[[defining-alerts-type-conditions]]
-=== Rule type and conditions
-
-Depending upon the {kib} app and context, you may be prompted to choose the type of rule you wish to create. Some apps will pre-select the type of rule for you.
-
-[role="screenshot"]
-image::images/rule-flyout-rule-type-selection.png[Choosing the type of rule to create]
-
-Each rule type provides its own way of defining the conditions to detect, but an expression formed by a series of clauses is a common pattern. Each clause has a UI control that allows you to define the clause. For example, in an index threshold rule the `WHEN` clause allows you to select an aggregation operation to apply to a numeric field.
-
-[role="screenshot"]
-image::images/rule-flyout-rule-conditions.png[UI for defining rule conditions on an index threshold rule]
-
-[float]
-[[defining-alerts-actions-details]]
-=== Action type and action details
-
-To add an action to a rule, you first select the type of connector:
-
-[role="screenshot"]
-image::images/rule-flyout-connector-type-selection.png[UI for selecting an action type]
-
-When an alert matches a condition, the rule is marked as _Active_ and assigned an action group. The actions in that group are triggered.
-When the condition is no longer detected, the rule is assigned to the _Recovered_ action group, which triggers any actions assigned to that group.
-
-**Run When** allows you to assign an action to an action group. This will trigger the action in accordance with your **Notify** setting.
-
-Each action must specify a <<alerting-concepts-connectors, connector>> instance. If no connectors exist for that action type, click *Add connector* to create one.
-
-Each action type exposes different properties. For example an email action allows you to set the recipients, the subject, and a message body in markdown format. See <<action-types>> for details on the types of actions provided by {kib} and their properties.
-
-[role="screenshot"]
-image::images/rule-flyout-action-details.png[UI for defining an email action]
-
-[float]
-[[defining-alerts-actions-variables]]
-==== Action variables
-Using the https://mustache.github.io/[Mustache] template syntax `{{variable name}}`, you can pass rule values at the time a condition is detected to an action. You can access the list of available variables using the "add variable" button. Although available variables differ by rule type, all rule types pass the following variables:
-
-`rule.id`:: The ID of the rule.
-`rule.name`:: The name of the rule.
-`rule.spaceId`:: The ID of the space for the rule.
-`rule.tags`:: The list of tags applied to the rule.
-`date`:: The date the rule scheduled the action, in ISO format.
-`alert.id`:: The ID of the alert that scheduled the action.
-`alert.actionGroup`:: The ID of the action group of the alert that scheduled the action.
-`alert.actionSubgroup`:: The action subgroup of the alert that scheduled the action.
-`alert.actionGroupName`:: The name of the action group of the alert that scheduled the action.
-`kibanaBaseUrl`:: The configured <<server-publicBaseUrl, `server.publicBaseUrl`>>. If not configured, this will be empty.
-
-[role="screenshot"]
-image::images/rule-flyout-action-variables.png[Passing rule values to an action]
-
-Some cases exist where the variable values will be "escaped", when used in a context where escaping is needed:
-
-- For the <<email-action-type, Email>> connector, the `message` action configuration property escapes any characters that would be interpreted as Markdown.
-- For the <<slack-action-type, Slack>> connector, the `message` action configuration property escapes any characters that would be interpreted as Slack Markdown.
-- For the <<webhook-action-type, Webhook>> connector, the `body` action configuration property escapes any characters that are invalid in JSON string values.
-
-Mustache also supports "triple braces" of the form `{{{variable name}}}`, which indicates no escaping should be done at all.  Care should be used when using this form, as it could end up rendering the variable content in such a way as to make the resulting parameter invalid or formatted incorrectly.
-
-Each rule type defines additional variables as properties of the variable `context`.  For example, if a rule type defines a variable `value`, it can be used in an action parameter as `{{context.value}}`.  
-
-For diagnostic or exploratory purposes, action variables whose values are objects, such as `context`, can be referenced directly as variables.  The resulting value will be a JSON representation of the object.  For example, if an action parameter includes `{{context}}`, it will expand to the JSON representation of all the variables and values provided by the rule type.
-
-You can attach more than one action. Clicking the "Add action" button will prompt you to select another rule type and repeat the above steps again.
-
-[role="screenshot"]
-image::images/rule-flyout-add-action.png[You can add multiple actions on a rule]
-
-[NOTE]
-==============================================
-Actions are not required on rules. You can run a rule without actions to understand its behavior, and then <<action-settings, configure actions>> later.
-==============================================
-
-[float]
-=== Manage rules
+==== General rule details
 
-To modify a rule after it was created, including muting or disabling it, use the <<alert-management, rule listing in the Management UI>>.
+This content has been moved to <<create-and-manage-rules>>.
\ No newline at end of file
diff --git a/docs/user/alerting/images/individual-mute-disable.png b/docs/user/alerting/images/individual-mute-disable.png
index 0ed2bfc0186c0..c9d8cd666f1d8 100644
Binary files a/docs/user/alerting/images/individual-mute-disable.png and b/docs/user/alerting/images/individual-mute-disable.png differ
diff --git a/docs/user/alerting/images/rule-flyout-action-no-connector.png b/docs/user/alerting/images/rule-flyout-action-no-connector.png
new file mode 100644
index 0000000000000..b8b0864e04226
Binary files /dev/null and b/docs/user/alerting/images/rule-flyout-action-no-connector.png differ
diff --git a/docs/user/alerting/index.asciidoc b/docs/user/alerting/index.asciidoc
index f8a5aacce8f0e..68cf3ee070b08 100644
--- a/docs/user/alerting/index.asciidoc
+++ b/docs/user/alerting/index.asciidoc
@@ -1,7 +1,8 @@
 include::alerting-getting-started.asciidoc[]
+include::alerting-setup.asciidoc[]
+include::create-and-manage-rules.asciidoc[]
 include::defining-rules.asciidoc[]
 include::rule-management.asciidoc[]
-include::rule-details.asciidoc[]
 include::stack-rules.asciidoc[]
 include::domain-specific-rules.asciidoc[]
 include::alerting-troubleshooting.asciidoc[]
diff --git a/docs/user/alerting/map-rules/geo-rule-types.asciidoc b/docs/user/alerting/map-rules/geo-rule-types.asciidoc
index 4b17145c2d149..eee7b59252205 100644
--- a/docs/user/alerting/map-rules/geo-rule-types.asciidoc
+++ b/docs/user/alerting/map-rules/geo-rule-types.asciidoc
@@ -30,8 +30,8 @@ than the current time minus the amount of the interval. If data older than
 
 [float]
 ==== Creating a geo rule
-Click the *Create* button in the <<alert-management, rule management UI>>.
-Complete the <<defining-alerts-general-details, general rule details>>.
+Click the *Create* button in the <<create-and-manage-rules, rule management UI>>.
+Complete the <<defining-rules-general-details, general rule details>>.
 
 [role="screenshot"]
 image::user/alerting/images/alert-types-tracking-select.png[Choosing a tracking rule type]
diff --git a/docs/user/alerting/rule-details.asciidoc b/docs/user/alerting/rule-details.asciidoc
deleted file mode 100644
index 6e743595e5c33..0000000000000
--- a/docs/user/alerting/rule-details.asciidoc
+++ /dev/null
@@ -1,33 +0,0 @@
-[role="xpack"]
-[[rule-details]]
-== Rule details
-
-
-The *Rule details* page tells you about the state of the rule and provides granular control over the actions it is taking. 
-
-[role="screenshot"]
-image::images/rule-details-alerts-active.png[Rule details page with three alerts]
-
-In this example, the rule detects when a site serves more than a threshold number of bytes in a 24 hour period. Three sites are above the threshold. These are called alerts - occurrences of the condition being detected - and the alert name, status, time of detection, and duration of the condition are shown in this view.
-
-Upon detection, each alert can trigger one or more actions. If the condition persists, the same actions will trigger either on the next scheduled rule check, or (if defined) after the re-notify period on the rule has passed. To prevent re-notification, you can suppress future actions by clicking on the eye icon to mute an individual alert. Muting means that the rule checks continue to run on a schedule, but that alert will not trigger any action.
-
-[role="screenshot"]
-image::images/rule-details-alert-muting.png[Muting an alert]
-
-Alerts will come and go from the list depending on whether they meet the rule conditions or not - unless they are muted. If a muted instance no longer meets the rule conditions, it will appear as inactive in the list. This prevents an alert from triggering actions if it reappears in the future.
-
-[role="screenshot"]
-image::images/rule-details-alerts-inactive.png[Rule details page with three inactive alerts]
-
-If you want to suppress actions on all current and future alerts, you can mute the entire rule. Rule checks continue to run and the alert list will update as alerts activate or deactivate, but no actions will be triggered.
-
-[role="screenshot"]
-image::images/rule-details-muting.png[Use the mute toggle to suppress all actions on current and future alerts]
-
-You can also disable a rule altogether. When disabled, the rule stops running checks altogether and will clear any alerts it is tracking. You may want to disable rules that are not currently needed to reduce the load on {kib} and {es}.
-
-[role="screenshot"]
-image::images/rule-details-disabling.png[Use the disable toggle to turn off rule checks and clear alerts tracked]
-
-* For further information on alerting concepts and examples, see <<alerting-getting-started>>.
diff --git a/docs/user/alerting/rule-management.asciidoc b/docs/user/alerting/rule-management.asciidoc
index b908bd03b0992..d6349a60e08eb 100644
--- a/docs/user/alerting/rule-management.asciidoc
+++ b/docs/user/alerting/rule-management.asciidoc
@@ -2,62 +2,4 @@
 [[alert-management]]
 == Managing rules
 
-
-The *Rules* tab provides a cross-app view of alerting. Different {kib} apps like {observability-guide}/create-alerts.html[*Observability*], {security-guide}/prebuilt-rules.html[*Security*], <<geo-alerting, *Maps*>> and <<xpack-ml, *Machine Learning*>> can offer their own rules. The *Rules* tab provides a central place to:
-
-* <<create-edit-rules, Create and edit>> rules
-* <<controlling-rules, Control rules>> including enabling/disabling, muting/unmuting, and deleting
-* Drill-down to <<rule-details, rule details>>
-
-[role="screenshot"]
-image:images/rules-and-connectors-ui.png[Example rule listing in the Rules and Connectors UI]
-
-For more information on alerting concepts and the types of rules and connectors available, see <<alerting-getting-started>>.
-
-[float]
-=== Finding rules
-
-The *Rules* tab lists all rules in the current space, including summary information about their execution frequency, tags, and type.
-
-The *search bar* can be used to quickly find rules by name or tag.
-
-[role="screenshot"]
-image::images/rules-filter-by-search.png[Filtering the rules list using the search bar]
-
-The *type* dropdown lets you filter to a subset of rule types.
-
-[role="screenshot"]
-image::images/rules-filter-by-type.png[Filtering the rules list by types of rule]
-
-The *Action type* dropdown lets you filter by the type of action used in the rule.
-
-[role="screenshot"]
-image::images/rules-filter-by-action-type.png[Filtering the rule list by type of action]
-
-[float]
-[[create-edit-rules]]
-=== Creating and editing rules
-
-Many rules must be created within the context of a {kib} app like <<metrics-app, Metrics>>, <<xpack-apm, APM>>, or <<uptime-app, Uptime>>, but others are generic. Generic rule types can be created in the *Rules* management UI by clicking the *Create* button. This will launch a flyout that guides you through selecting a rule type and configuring its properties. Refer to <<stack-rules>> for details on what types of rules are available and how to configure them.
-
-After a rule is created, you can re-open the flyout and change a rule's properties by clicking the *Edit* button shown on each row of the rule listing.
-
-
-[float]
-[[controlling-rules]]
-=== Controlling rules
-
-The rule listing allows you to quickly mute/unmute, disable/enable, and delete individual rules by clicking the action button. 
-
-[role="screenshot"]
-image:images/individual-mute-disable.png[The actions button allows an individual rule to be muted, disabled, or deleted]
-
-These operations can also be performed in bulk by multi-selecting rules and clicking the *Manage rules* button:
-
-[role="screenshot"]
-image:images/bulk-mute-disable.png[The Manage rules button lets you mute/unmute, enable/disable, and delete in bulk]
-
-[float]
-=== Required permissions
-
-Access to rules is granted based on your privileges to alerting-enabled features. See <<alerting-security, Alerting Security>> for more information.
+This content has been moved to <<create-and-manage-rules>>.
\ No newline at end of file
diff --git a/docs/user/alerting/stack-rules/es-query.asciidoc b/docs/user/alerting/stack-rules/es-query.asciidoc
index c62ebbf4bf2bc..5615c79a6c9c7 100644
--- a/docs/user/alerting/stack-rules/es-query.asciidoc
+++ b/docs/user/alerting/stack-rules/es-query.asciidoc
@@ -7,7 +7,7 @@ The {es} query rule type runs a user-configured {es} query, compares the number
 [float]
 ==== Create the rule
 
-Fill in the <<defining-alerts-general-details, rule details>>, then select *{es} query*.
+Fill in the <<defining-rules-general-details, rule details>>, then select *{es} query*.
 
 [float]
 ==== Define the conditions
@@ -22,12 +22,12 @@ Size:: This clause specifies the number of documents to pass to the configured a
 {es} query:: This clause specifies the ES DSL query to execute. The number of documents that match this query will be evaulated against the threshold
 condition. Aggregations are not supported at this time. 
 Threshold:: This clause defines a threshold value and a comparison operator  (`is above`, `is above or equals`, `is below`, `is below or equals`, or `is between`). The number of documents that match the specified query is compared to this threshold.
-Time window:: This clause determines how far back to search for documents, using the *time field* set in the *index* clause. Generally this value should be set to a value higher than the *check every* value in the <<defining-alerts-general-details, general rule details>>, to avoid gaps in detection. 
+Time window:: This clause determines how far back to search for documents, using the *time field* set in the *index* clause. Generally this value should be set to a value higher than the *check every* value in the <<defining-rules-general-details, general rule details>>, to avoid gaps in detection. 
 
 [float]
 ==== Add action variables
 
-<<defining-alerts-actions-details, Add an action>> to run when the rule condition is met. The following variables are specific to the {es} query rule. You can also specify <<defining-alerts-actions-variables, variables common to all rules>>.
+<<defining-rules-actions-details, Add an action>> to run when the rule condition is met. The following variables are specific to the {es} query rule. You can also specify <<defining-rules-actions-variables, variables common to all rules>>.
 
 `context.title`:: A preconstructed title for the rule. Example: `rule term match alert query matched`.
 `context.message`:: A preconstructed message for the rule. Example: +
diff --git a/docs/user/alerting/stack-rules/index-threshold.asciidoc b/docs/user/alerting/stack-rules/index-threshold.asciidoc
index 43b750b85fb3b..8c45c158414f4 100644
--- a/docs/user/alerting/stack-rules/index-threshold.asciidoc
+++ b/docs/user/alerting/stack-rules/index-threshold.asciidoc
@@ -7,7 +7,7 @@ The index threshold rule type runs an {es} query. It aggregates field values fro
 [float]
 ==== Create the rule
 
-Fill in the <<defining-alerts-general-details, rule details>>, then select *Index Threshold*.
+Fill in the <<defining-rules-general-details, rule details>>, then select *Index Threshold*.
 
 [float]
 ==== Define the conditions
@@ -19,9 +19,9 @@ image::user/alerting/images/rule-types-index-threshold-conditions.png[Five claus
 
 Index:: This clause requires an *index or index pattern* and a *time field* that will be used for the *time window*.
 When:: This clause specifies how the value to be compared to the threshold is calculated. The value is calculated by aggregating a numeric field a the *time window*. The aggregation options are: `count`, `average`, `sum`, `min`, and `max`. When using `count` the document count is used, and an aggregation field is not necessary. 
-Over/Grouped Over:: This clause lets you configure whether the aggregation is applied over all documents, or should be split into groups using a grouping field. If grouping is used, an  <<alerting-concepts-alert-instances, alert>> will be created for each group when it exceeds the threshold. To limit the number of alerts on high cardinality fields, you must specify the number of groups to check against the threshold. Only the *top* groups are checked.
+Over/Grouped Over:: This clause lets you configure whether the aggregation is applied over all documents, or should be split into groups using a grouping field. If grouping is used, an  <<alerting-concepts-alerts, alert>> will be created for each group when it exceeds the threshold. To limit the number of alerts on high cardinality fields, you must specify the number of groups to check against the threshold. Only the *top* groups are checked.
 Threshold:: This clause defines a threshold value and a comparison operator  (one of `is above`, `is above or equals`, `is below`, `is below or equals`, or `is between`). The result of the aggregation is compared to this threshold. 
-Time window:: This clause determines how far back to search for documents, using the *time field* set in the *index* clause. Generally this value should be to a value higher than the *check every* value in the <<defining-alerts-general-details, general rule details>>, to avoid gaps in detection. 
+Time window:: This clause determines how far back to search for documents, using the *time field* set in the *index* clause. Generally this value should be to a value higher than the *check every* value in the <<defining-rules-general-details, general rule details>>, to avoid gaps in detection. 
 
 If data is available and all clauses have been defined, a preview chart will render the threshold value and display a line chart showing the value for the last 30 intervals. This can provide an indication of recent values and their proximity to the threshold, and help you tune the clauses. 
 
@@ -31,7 +31,7 @@ image::user/alerting/images/rule-types-index-threshold-preview.png[Five clauses
 [float]
 ==== Add action variables
 
-<<defining-alerts-actions-details, Add an action>> to run when the rule condition is met. The following variables are specific to the index threshold rule. You can also specify <<defining-alerts-actions-variables, variables common to all rules>>.
+<<defining-rules-actions-details, Add an action>> to run when the rule condition is met. The following variables are specific to the index threshold rule. You can also specify <<defining-rules-actions-variables, variables common to all rules>>.
 
 `context.title`:: A preconstructed title for the rule. Example: `rule kibana sites - high egress met threshold`.
 `context.message`:: A preconstructed message for the rule. Example: +
diff --git a/docs/user/dashboard/aggregation-reference.asciidoc b/docs/user/dashboard/aggregation-reference.asciidoc
index 7d5547fe3c3c5..39e596df4af34 100644
--- a/docs/user/dashboard/aggregation-reference.asciidoc
+++ b/docs/user/dashboard/aggregation-reference.asciidoc
@@ -188,6 +188,12 @@ For information about {es} metrics aggregations, refer to {ref}/search-aggregati
 
 | Type | Agg-based | Markdown | Lens | TSVB
 
+| Metrics with filters
+|
+^| X
+|
+|
+
 | Average
 ^| X
 ^| X
@@ -221,7 +227,7 @@ For information about {es} metrics aggregations, refer to {ref}/search-aggregati
 | Percentiles
 ^| X
 ^| X
-| 
+^| X
 ^| X
 
 | Percentiles Rank
@@ -230,10 +236,10 @@ For information about {es} metrics aggregations, refer to {ref}/search-aggregati
 | 
 ^| X
 
-| Top hit 
+| Top hit (Last value)
+^| X
 ^| X
 ^| X
-| 
 ^| X
 
 | Value count 
@@ -266,7 +272,7 @@ For information about {es} pipeline aggregations, refer to {ref}/search-aggregat
 | Derivative  
 ^| X
 ^| X
-| 
+^| X
 ^| X
 
 | Max bucket   
@@ -290,13 +296,13 @@ For information about {es} pipeline aggregations, refer to {ref}/search-aggregat
 | Moving average  
 ^| X
 ^| X
-| 
+^| X
 ^| X
 
 | Cumulative sum 
 ^| X
 ^| X
-| 
+^| X
 ^| X
 
 | Bucket script 
diff --git a/docs/user/dashboard/lens.asciidoc b/docs/user/dashboard/lens.asciidoc
index 3b3a7a9ee527d..9f17a380bc209 100644
--- a/docs/user/dashboard/lens.asciidoc
+++ b/docs/user/dashboard/lens.asciidoc
@@ -147,14 +147,24 @@ For the answers to common *Lens* questions, review the following.
 
 [float]
 [[kql-]]
-===== When should I use the Filter function instead of KQL filters?
+===== When should I use the top filter bar, filters function, or "Filter by"?
 
-The easiest way to apply KQL filters is to use <<semi-structured-search>>, but you can also use the *Filters* function in the following scenarios:
+Using the top <<semi-structured-search>> bar is best when you want to focus on a known set of
+data for all the visualization results. These top level filters are combined with other filters
+using AND logic.
+
+Use the *Filters* function in the following scenarios:
 
 * When you want to apply more than one KQL filter to the visualization.
 
 * When you want to apply the KQL filter to a single layer, which allows you to visualize filtered and unfiltered data.
 
+Use the *Filter by* advanced option in the following scenarios:
+
+* When you want to assign a custom color to each filter in a bar, line or area chart.
+
+* When you want to build a complex table, such as showing both failure rate and overall.
+
 [float]
 [[when-should-i-normalize-the-data-by-unit-or-use-a-custom-interval]]
 ===== When should I normalize the data by unit or use a custom interval?
diff --git a/docs/user/introduction.asciidoc b/docs/user/introduction.asciidoc
index 25780d303eec4..82ca11f2162fd 100644
--- a/docs/user/introduction.asciidoc
+++ b/docs/user/introduction.asciidoc
@@ -195,7 +195,7 @@ When the rule triggers, you can send a notification to a system that is part of
 your daily workflow. {kib} integrates with email, Slack, PagerDuty, and ServiceNow,
 to name a few.
 
-A dedicated view for creating, searching, and editing rules is in <<alert-management,*Rules and Connectors*>>.
+A dedicated view for creating, searching, and editing rules is in <<create-and-manage-rules,*Rules and Connectors*>>.
 
 [role="screenshot"]
 image::images/rules-and-connectors.png[Rules and Connectors view]
@@ -437,7 +437,7 @@ the <<get-started,{kib} Quick start>>.
 |<<manage-data,Stack Management > Data>>
 
 |Set up rules
-|<<alert-management,Stack Management > Rules and Connectors>>
+|<<create-and-manage-rules,Stack Management > Rules and Connectors>>
 
 |Organize your workspace and users
 |<<xpack-spaces,Stack Management > Spaces>>
diff --git a/docs/user/management.asciidoc b/docs/user/management.asciidoc
index c5fabb15dc4de..b86fa82c30381 100644
--- a/docs/user/management.asciidoc
+++ b/docs/user/management.asciidoc
@@ -75,7 +75,7 @@ You can add and remove remote clusters, and check their connectivity.
 |===
 
 | <<alerting-getting-started, Rules&nbsp;and Connectors>>
-| Centrally <<alert-management, manage your rules>> across {kib}. Create and <<connector-management, manage reusable
+| Centrally <<create-and-manage-rules, manage your rules>> across {kib}. Create and <<connector-management, manage reusable
 connectors>> for triggering actions.
 
 | <<reporting-getting-started, Reporting>>
diff --git a/docs/user/monitoring/images/monitoring-kibana-alerting-notification.png b/docs/user/monitoring/images/monitoring-kibana-alerting-notification.png
new file mode 100644
index 0000000000000..90951d18e667b
Binary files /dev/null and b/docs/user/monitoring/images/monitoring-kibana-alerting-notification.png differ
diff --git a/docs/user/monitoring/images/monitoring-kibana-alerting-setup-mode.png b/docs/user/monitoring/images/monitoring-kibana-alerting-setup-mode.png
new file mode 100644
index 0000000000000..146992da5837a
Binary files /dev/null and b/docs/user/monitoring/images/monitoring-kibana-alerting-setup-mode.png differ
diff --git a/docs/user/monitoring/kibana-alerts.asciidoc b/docs/user/monitoring/kibana-alerts.asciidoc
index 58bf419d8d54a..6046e67db62f1 100644
--- a/docs/user/monitoring/kibana-alerts.asciidoc
+++ b/docs/user/monitoring/kibana-alerts.asciidoc
@@ -1,100 +1,109 @@
 [role="xpack"]
 [[kibana-alerts]]
-= {kib} Alerts
+= {kib} alerts
 
 The {stack} {monitor-features} provide
-<<alerting-getting-started,{kib} alerts>> out-of-the box to notify you of
-potential issues in the {stack}. These alerts are preconfigured based on the
+<<alerting-getting-started,{kib} alerting rules>> out-of-the box to notify you
+of potential issues in the {stack}. These rules are preconfigured based on the
 best practices recommended by Elastic. However, you can tailor them to meet your 
 specific needs.
 
-When you open *{stack-monitor-app}*, the preconfigured {kib} alerts are
-created automatically. If you collect monitoring data from multiple clusters,
-these alerts can search, detect, and notify on various conditions across the
-clusters. The alerts are visible alongside your existing {watcher} cluster
-alerts. You can view details about the alerts that are active and view health
-and performance data for {es}, {ls}, and Beats in real time, as well as
-analyze past performance. You can also modify active alerts.
+[role="screenshot"]
+image::user/monitoring/images/monitoring-kibana-alerts.png["{kib} alerts in {stack-monitor-app}"]
+
+When you open *{stack-monitor-app}*, the preconfigured rules are created 
+automatically. They are initially configured to detect and notify on various 
+conditions across your monitored clusters. You can view notifications for: *Cluster health*, *Resource utilization*, and *Errors and exceptions* for {es}
+in real time.
+
+NOTE: The default {watcher} based "cluster alerts" for {stack-monitor-app} have 
+been recreated as rules in {kib} {alert-features}. For this reason, the existing 
+{watcher} email action 
+`monitoring.cluster_alerts.email_notifications.email_address` no longer works.
+The default action for all {stack-monitor-app} rules is to write to {kib} logs 
+and display a notification in the UI.
 
 [role="screenshot"]
-image::user/monitoring/images/monitoring-kibana-alerts.png["Kibana alerts in the Stack Monitoring app"]
+image::user/monitoring/images/monitoring-kibana-alerting-notification.png["{kib} alerting notifications in {stack-monitor-app}"]
 
-To review and modify all the available alerts, use
-<<alert-management,*{alerts-ui}*>> in *{stack-manage-app}*.
+
+[role="screenshot"]
+image::user/monitoring/images/monitoring-kibana-alerting-setup-mode.png["Modify {kib} alerting rules in {stack-monitor-app}"]
 
 [discrete]
 [[kibana-alerts-cpu-threshold]]
-== CPU threshold
+== CPU usage threshold
 
-This alert is triggered when a node runs a consistently high CPU load. By
-default, the trigger condition is set at 85% or more averaged over the last 5
-minutes. The alert is grouped across all the nodes of the cluster by running
-checks on a schedule time of 1 minute with a re-notify interval of 1 day. 
+This rule checks for {es} nodes that run a consistently high CPU load. By
+default, the condition is set at 85% or more averaged over the last 5 minutes.
+The rule is grouped across all the nodes of the cluster by running checks on a
+schedule time of 1 minute with a re-notify interval of 1 day.
 
 [discrete]
 [[kibana-alerts-disk-usage-threshold]]
 == Disk usage threshold
 
-This alert is triggered when a node is nearly at disk capacity. By
-default, the trigger condition is set at 80% or more averaged over the last 5
-minutes. The alert is grouped across all the nodes of the cluster by running
-checks on a schedule time of 1 minute with a re-notify interval of 1 day. 
+This rule checks for {es} nodes that are nearly at disk capacity. By default,
+the condition is set at 80% or more averaged over the last 5 minutes. The rule
+is grouped across all the nodes of the cluster by running checks on a schedule
+time of 1 minute with a re-notify interval of 1 day.
 
 [discrete]
 [[kibana-alerts-jvm-memory-threshold]]
 == JVM memory threshold
 
-This alert is triggered when a node runs a consistently high JVM memory usage. By
-default, the trigger condition is set at 85% or more averaged over the last 5
-minutes. The alert is grouped across all the nodes of the cluster by running
-checks on a schedule time of 1 minute with a re-notify interval of 1 day. 
+This rule checks for {es} nodes that use a high amount of JVM memory. By
+default, the condition is set at 85% or more averaged over the last 5 minutes.
+The rule is grouped across all the nodes of the cluster by running checks on a
+schedule time of 1 minute with a re-notify interval of 1 day. 
 
 [discrete]
 [[kibana-alerts-missing-monitoring-data]]
 == Missing monitoring data
 
-This alert is triggered when any stack products nodes or instances stop sending
-monitoring data. By default, the trigger condition is set to missing for 15 minutes
-looking back 1 day. The alert is grouped across all the nodes of the cluster by running
-checks on a schedule time of 1 minute with a re-notify interval of 6 hours. 
+This rule checks for {es} nodes that stop sending monitoring data. By default, 
+the condition is set to missing for 15 minutes looking back 1 day. The rule is
+grouped across all the {es} nodes of the cluster by running checks on a schedule
+time of 1 minute with a re-notify interval of 6 hours. 
 
 [discrete]
 [[kibana-alerts-thread-pool-rejections]]
 == Thread pool rejections (search/write)
 
-This alert is triggered when a node experiences thread pool rejections. By
-default, the trigger condition is set at 300 or more over the last 5
-minutes. The alert is grouped across all the nodes of the cluster by running
-checks on a schedule time of 1 minute with a re-notify interval of 1 day. 
-Thresholds can be set independently for `search` and `write` type rejections.
+This rule checks for {es} nodes that experience thread pool rejections. By 
+default, the condition is set at 300 or more over the last 5 minutes. The rule
+is grouped across all the nodes of the cluster by running checks on a schedule
+time of 1 minute with a re-notify interval of 1 day. Thresholds can be set
+independently for `search` and `write` type rejections.
 
 [discrete]
 [[kibana-alerts-ccr-read-exceptions]]
 == CCR read exceptions
 
-This alert is triggered if a read exception has been detected on any of the 
-replicated clusters. The trigger condition is met if 1 or more read exceptions 
-are detected in the last hour. The alert is grouped across all replicated clusters 
-by running checks on a schedule time of 1 minute with a re-notify interval of 6 hours. 
+This rule checks for read exceptions on any of the replicated {es} clusters. The
+condition is met if 1 or more read exceptions are detected in the last hour. The
+rule is grouped across all replicated clusters by running checks on a schedule 
+time of 1 minute with a re-notify interval of 6 hours. 
 
 [discrete]
 [[kibana-alerts-large-shard-size]]
 == Large shard size
 
-This alert is triggered if a large average shard size (across associated primaries) is found on any of the 
-specified index patterns. The trigger condition is met if an index's average shard size is 
-55gb or higher in the last 5 minutes. The alert is grouped across all indices that match 
-the default pattern of `*` by running checks on a schedule time of 1 minute with a re-notify 
-interval of 12 hours.
+This rule checks for a large average shard size (across associated primaries) on
+any of the specified index patterns in an {es} cluster. The condition is met if
+an index's average shard size is 55gb or higher in the last 5 minutes. The rule
+is grouped across all indices that match the default pattern of `-.*` by running
+checks on a schedule time of 1 minute with a re-notify interval of 12 hours.
 
 [discrete]
 [[kibana-alerts-cluster-alerts]]
-== Cluster alerts
+== Cluster alerting
 
-These alerts summarize the current status of your {stack}. You can drill down into the metrics 
-to view more information about your cluster and specific nodes, instances, and indices.
+These rules check the current status of your {stack}. You can drill down into
+the metrics to view more information about your cluster and specific nodes, instances, and indices.
 
-An alert will be triggered if any of the following conditions are met within the last minute:
+An action is triggered if any of the following conditions are met within the
+last minute:
 
 * {es} cluster health status is yellow (missing at least one replica)
 or red (missing at least one primary).
@@ -110,7 +119,7 @@ versions reporting stats to the same monitoring cluster.
 --
 If you do not preserve the data directory when upgrading a {kib} or
 Logstash node, the instance is assigned a new persistent UUID and shows up
-as a new instance
+as a new instance.
 --
 * Subscription license expiration. When the expiration date
 approaches, you will get notifications with a severity level relative to how
diff --git a/docs/user/production-considerations/alerting-production-considerations.asciidoc b/docs/user/production-considerations/alerting-production-considerations.asciidoc
index 6294a4fe6f14a..bd19a11435a99 100644
--- a/docs/user/production-considerations/alerting-production-considerations.asciidoc
+++ b/docs/user/production-considerations/alerting-production-considerations.asciidoc
@@ -19,7 +19,7 @@ When relying on rules and actions as mission critical services, make sure you fo
 By default, each {kib} instance polls for work at three second intervals, and can run a maximum of ten concurrent tasks.
 These tasks are then run on the {kib} server.
 
-Rules are recurring background tasks which are rescheduled according to the <<defining-alerts-general-details, check interval>> on completion.
+Rules are recurring background tasks which are rescheduled according to the <<defining-rules-general-details, check interval>> on completion.
 Actions are non-recurring background tasks which are deleted on completion.
 
 For more details on Task Manager, see <<task-manager-background-tasks>>.
@@ -42,7 +42,7 @@ As rules and actions leverage background tasks to perform the majority of work,
 
 When estimating the required task throughput, keep the following in mind:
 
-* Each rule uses a single recurring task that is scheduled to run at the cadence defined by its <<defining-alerts-general-details,check interval>>.
+* Each rule uses a single recurring task that is scheduled to run at the cadence defined by its <<defining-rules-general-details,check interval>>.
 * Each action uses a single task. However, because <<alerting-concepts-suppressing-duplicate-notifications,actions are taken per instance>>, alerts can generate a large number of non-recurring tasks.
 
 It is difficult to predict how much throughput is needed to ensure all rules and actions are executed at consistent schedules.
diff --git a/packages/kbn-monaco/src/monaco_imports.ts b/packages/kbn-monaco/src/monaco_imports.ts
index 872ac46352cf3..92ea23347c374 100644
--- a/packages/kbn-monaco/src/monaco_imports.ts
+++ b/packages/kbn-monaco/src/monaco_imports.ts
@@ -21,5 +21,6 @@ import 'monaco-editor/esm/vs/editor/contrib/folding/folding.js'; // Needed for f
 import 'monaco-editor/esm/vs/editor/contrib/suggest/suggestController.js'; // Needed for suggestions
 import 'monaco-editor/esm/vs/editor/contrib/hover/hover.js'; // Needed for hover
 import 'monaco-editor/esm/vs/editor/contrib/parameterHints/parameterHints.js'; // Needed for signature
+import 'monaco-editor/esm/vs/editor/contrib/bracketMatching/bracketMatching.js'; // Needed for brackets matching highlight
 
 export { monaco };
diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js
index e455f487d1384..1311eb4d7c638 100644
--- a/packages/kbn-pm/dist/index.js
+++ b/packages/kbn-pm/dist/index.js
@@ -48479,7 +48479,7 @@ async function runBazelCommandWithRunner(bazelCommandRunner, bazelArgs, offline
     stdio: 'pipe'
   });
 
-  if (offline) {
+  if (offline || !offline) {
     bazelArgs = [...bazelArgs, '--config=offline'];
   }
 
diff --git a/packages/kbn-pm/src/utils/bazel/run.ts b/packages/kbn-pm/src/utils/bazel/run.ts
index c030081e53daa..5f3743876e0e4 100644
--- a/packages/kbn-pm/src/utils/bazel/run.ts
+++ b/packages/kbn-pm/src/utils/bazel/run.ts
@@ -29,7 +29,7 @@ async function runBazelCommandWithRunner(
     stdio: 'pipe',
   };
 
-  if (offline) {
+  if (offline || !offline) {
     bazelArgs = [...bazelArgs, '--config=offline'];
   }
 
diff --git a/packages/kbn-test/src/kbn_client/kbn_client_import_export.ts b/packages/kbn-test/src/kbn_client/kbn_client_import_export.ts
index 5fd30929fecf6..88953cdbaed7c 100644
--- a/packages/kbn-test/src/kbn_client/kbn_client_import_export.ts
+++ b/packages/kbn-test/src/kbn_client/kbn_client_import_export.ts
@@ -48,7 +48,12 @@ export class KbnClientImportExport {
       path = `${path}.json`;
     }
 
-    const absolutePath = Path.resolve(this.baseDir, path);
+    return Path.resolve(this.baseDir, path);
+  }
+
+  private resolveAndValidatePath(path: string) {
+    const absolutePath = this.resolvePath(path);
+
     if (!existsSync(absolutePath)) {
       throw new Error(
         `unable to resolve path [${path}] to import/export, resolved relative to [${this.baseDir}]`
@@ -59,7 +64,7 @@ export class KbnClientImportExport {
   }
 
   async load(path: string, options?: { space?: string }) {
-    const src = this.resolvePath(path);
+    const src = this.resolveAndValidatePath(path);
     this.log.debug('resolved import for', path, 'to', src);
 
     const objects = await parseArchive(src);
@@ -94,7 +99,7 @@ export class KbnClientImportExport {
   }
 
   async unload(path: string, options?: { space?: string }) {
-    const src = this.resolvePath(path);
+    const src = this.resolveAndValidatePath(path);
     this.log.debug('unloading docs from archive at', src);
 
     const objects = await parseArchive(src);
@@ -143,6 +148,7 @@ export class KbnClientImportExport {
       })
       .join('\n\n');
 
+    await Fs.mkdir(Path.dirname(dest), { recursive: true });
     await Fs.writeFile(dest, fileContents, 'utf-8');
 
     this.log.success('Exported', objects.length, 'saved objects to', dest);
diff --git a/packages/kbn-tinymath/grammar/grammar.peggy b/packages/kbn-tinymath/grammar/grammar.peggy
index cbcb0b91bfea9..1c6f8c3334c23 100644
--- a/packages/kbn-tinymath/grammar/grammar.peggy
+++ b/packages/kbn-tinymath/grammar/grammar.peggy
@@ -1,16 +1,16 @@
 // tinymath parsing grammar
 
 {
-   function simpleLocation (location) {
-  // Returns an object representing the position of the function within the expression,
-  // demarcated by the position of its first character and last character. We calculate these values
-  // using the offset because the expression could span multiple lines, and we don't want to deal
-  // with column and line values.
-  return {
-   min: location.start.offset,
-   max: location.end.offset
+  function simpleLocation (location) {
+    // Returns an object representing the position of the function within the expression,
+    // demarcated by the position of its first character and last character. We calculate these values
+    // using the offset because the expression could span multiple lines, and we don't want to deal
+    // with column and line values.
+    return {
+      min: location.start.offset,
+      max: location.end.offset
+    }
   }
- }
 }
 
 start
@@ -74,26 +74,34 @@ Expression
   = AddSubtract
 
 AddSubtract
-  = _ left:MultiplyDivide rest:(('+' / '-') MultiplyDivide)* _ {
-    return rest.reduce((acc, curr) => ({
+  = _ left:MultiplyDivide rest:(('+' / '-') MultiplyDivide)+ _ {
+    const topLevel = rest.reduce((acc, curr) => ({
       type: 'function',
       name: curr[0] === '+' ? 'add' : 'subtract',
       args: [acc, curr[1]],
-      location: simpleLocation(location()),
-      text: text()
-    }), left)
+    }), left);
+    if (typeof topLevel === 'object') {
+      topLevel.location = simpleLocation(location());
+      topLevel.text = text();
+    }
+    return topLevel;
   }
+  / MultiplyDivide
 
 MultiplyDivide
   = _ left:Factor rest:(('*' / '/') Factor)* _ {
-    return rest.reduce((acc, curr) => ({
+    const topLevel = rest.reduce((acc, curr) => ({
       type: 'function',
       name: curr[0] === '*' ? 'multiply' : 'divide',
       args: [acc, curr[1]],
-      location: simpleLocation(location()),
-      text: text()
-    }), left)
+    }), left);
+    if (typeof topLevel === 'object') {
+      topLevel.location = simpleLocation(location());
+      topLevel.text = text();
+    }
+    return topLevel;
   }
+  / Factor
 
 Factor
   = Group
diff --git a/packages/kbn-tinymath/index.d.ts b/packages/kbn-tinymath/index.d.ts
index c3c32a59fa15a..8e15d86c88fc8 100644
--- a/packages/kbn-tinymath/index.d.ts
+++ b/packages/kbn-tinymath/index.d.ts
@@ -24,9 +24,11 @@ export interface TinymathLocation {
 export interface TinymathFunction {
   type: 'function';
   name: string;
-  text: string;
   args: TinymathAST[];
-  location: TinymathLocation;
+  // Location is not guaranteed because PEG grammars are not left-recursive
+  location?: TinymathLocation;
+  // Text is not guaranteed because PEG grammars are not left-recursive
+  text?: string;
 }
 
 export interface TinymathVariable {
diff --git a/packages/kbn-tinymath/test/library.test.js b/packages/kbn-tinymath/test/library.test.js
index bf1c7a9dbc5fb..bbc8503684fd4 100644
--- a/packages/kbn-tinymath/test/library.test.js
+++ b/packages/kbn-tinymath/test/library.test.js
@@ -41,6 +41,35 @@ describe('Parser', () => {
     });
   });
 
+  describe('Math', () => {
+    it('converts basic symbols into left-to-right pairs', () => {
+      expect(parse('a + b + c - d')).toEqual({
+        args: [
+          {
+            name: 'add',
+            type: 'function',
+            args: [
+              {
+                name: 'add',
+                type: 'function',
+                args: [
+                  expect.objectContaining({ location: { min: 0, max: 2 } }),
+                  expect.objectContaining({ location: { min: 3, max: 6 } }),
+                ],
+              },
+              expect.objectContaining({ location: { min: 7, max: 10 } }),
+            ],
+          },
+          expect.objectContaining({ location: { min: 11, max: 13 } }),
+        ],
+        name: 'subtract',
+        type: 'function',
+        text: 'a + b + c - d',
+        location: { min: 0, max: 13 },
+      });
+    });
+  });
+
   describe('Variables', () => {
     it('strings', () => {
       expect(parse('f')).toEqual(variableEqual('f'));
@@ -263,6 +292,8 @@ describe('Evaluate', () => {
     expect(evaluate('5/20')).toEqual(0.25);
     expect(evaluate('1 + 1 + 2 + 3 + 12')).toEqual(19);
     expect(evaluate('100 / 10 / 10')).toEqual(1);
+    expect(evaluate('0 * 1 - 100 / 10 / 10')).toEqual(-1);
+    expect(evaluate('100 / (10 / 10)')).toEqual(100);
   });
 
   it('equations with functions', () => {
diff --git a/src/cli_plugin/install/index.js b/src/cli_plugin/install/index.js
index 2683dd41d2bb3..dbad6bc8ba19c 100644
--- a/src/cli_plugin/install/index.js
+++ b/src/cli_plugin/install/index.js
@@ -24,7 +24,7 @@ function processCommand(command, options) {
 
   const logger = new Logger(settings);
 
-  logWarnings(settings, logger);
+  logWarnings(logger);
   install(settings, logger);
 }
 
diff --git a/src/cli_plugin/remove/index.js b/src/cli_plugin/remove/index.js
index 329f506520c24..3f571e605028f 100644
--- a/src/cli_plugin/remove/index.js
+++ b/src/cli_plugin/remove/index.js
@@ -24,7 +24,7 @@ function processCommand(command, options) {
 
   const logger = new Logger(settings);
 
-  logWarnings(settings, logger);
+  logWarnings(logger);
   remove(settings, logger);
 }
 
diff --git a/src/core/public/application/integration_tests/router.test.tsx b/src/core/public/application/integration_tests/router.test.tsx
index 55c18e49cba13..2543d22ee6d31 100644
--- a/src/core/public/application/integration_tests/router.test.tsx
+++ b/src/core/public/application/integration_tests/router.test.tsx
@@ -96,7 +96,7 @@ describe('AppRouter', () => {
 
     expect(app1.mounter.mount).toHaveBeenCalled();
     expect(dom?.html()).toMatchInlineSnapshot(`
-      "<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
+      "<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
       basename: /app/app1
       html: <span>App 1</span>
       </div></div>"
@@ -108,7 +108,7 @@ describe('AppRouter', () => {
     expect(app1Unmount).toHaveBeenCalled();
     expect(app2.mounter.mount).toHaveBeenCalled();
     expect(dom?.html()).toMatchInlineSnapshot(`
-      "<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
+      "<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
       basename: /app/app2
       html: <div>App 2</div>
       </div></div>"
@@ -122,7 +122,7 @@ describe('AppRouter', () => {
 
     expect(standardApp.mounter.mount).toHaveBeenCalled();
     expect(dom?.html()).toMatchInlineSnapshot(`
-      "<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
+      "<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
       basename: /app/app1
       html: <span>App 1</span>
       </div></div>"
@@ -134,7 +134,7 @@ describe('AppRouter', () => {
     expect(standardAppUnmount).toHaveBeenCalled();
     expect(chromelessApp.mounter.mount).toHaveBeenCalled();
     expect(dom?.html()).toMatchInlineSnapshot(`
-      "<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
+      "<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
       basename: /chromeless-a/path
       html: <div>Chromeless A</div>
       </div></div>"
@@ -146,7 +146,7 @@ describe('AppRouter', () => {
     expect(chromelessAppUnmount).toHaveBeenCalled();
     expect(standardApp.mounter.mount).toHaveBeenCalledTimes(2);
     expect(dom?.html()).toMatchInlineSnapshot(`
-      "<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
+      "<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
       basename: /app/app1
       html: <span>App 1</span>
       </div></div>"
@@ -160,7 +160,7 @@ describe('AppRouter', () => {
 
     expect(chromelessAppA.mounter.mount).toHaveBeenCalled();
     expect(dom?.html()).toMatchInlineSnapshot(`
-      "<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
+      "<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
       basename: /chromeless-a/path
       html: <div>Chromeless A</div>
       </div></div>"
@@ -172,7 +172,7 @@ describe('AppRouter', () => {
     expect(chromelessAppAUnmount).toHaveBeenCalled();
     expect(chromelessAppB.mounter.mount).toHaveBeenCalled();
     expect(dom?.html()).toMatchInlineSnapshot(`
-      "<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
+      "<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
       basename: /chromeless-b/path
       html: <div>Chromeless B</div>
       </div></div>"
@@ -184,7 +184,7 @@ describe('AppRouter', () => {
     expect(chromelessAppBUnmount).toHaveBeenCalled();
     expect(chromelessAppA.mounter.mount).toHaveBeenCalledTimes(2);
     expect(dom?.html()).toMatchInlineSnapshot(`
-      "<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
+      "<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
       basename: /chromeless-a/path
       html: <div>Chromeless A</div>
       </div></div>"
diff --git a/src/core/public/application/ui/app_container.scss b/src/core/public/application/ui/app_container.scss
index 4f8fec10a97e1..d30db740505d1 100644
--- a/src/core/public/application/ui/app_container.scss
+++ b/src/core/public/application/ui/app_container.scss
@@ -1,5 +1,5 @@
 .appContainer__loading {
-  position: fixed;
+  position: absolute;
   top: 50%;
   left: 50%;
   transform: translate(-50%, -50%);
diff --git a/src/core/public/application/ui/app_container.tsx b/src/core/public/application/ui/app_container.tsx
index 02d321095b373..0312c707e1049 100644
--- a/src/core/public/application/ui/app_container.tsx
+++ b/src/core/public/application/ui/app_container.tsx
@@ -5,6 +5,7 @@
  * in compliance with, at your election, the Elastic License 2.0 or the Server
  * Side Public License, v 1.
  */
+import './app_container.scss';
 
 import React, {
   Fragment,
@@ -16,11 +17,12 @@ import React, {
 } from 'react';
 import { EuiLoadingElastic } from '@elastic/eui';
 
+import { i18n } from '@kbn/i18n';
 import type { MountPoint } from '../../types';
 import { AppLeaveHandler, AppStatus, AppUnmount, Mounter } from '../types';
 import { AppNotFound } from './app_not_found_screen';
 import { ScopedHistory } from '../scoped_history';
-import './app_container.scss';
+import { APP_WRAPPER_CLASS } from '../../../utils';
 
 interface Props {
   /** Path application is mounted on without the global basePath */
@@ -107,12 +109,16 @@ export const AppContainer: FunctionComponent<Props> = ({
   return (
     <Fragment>
       {appNotFound && <AppNotFound />}
-      {showSpinner && (
-        <div className="appContainer__loading">
-          <EuiLoadingElastic aria-label="Loading application" size="xxl" />
-        </div>
+      {showSpinner && !appNotFound && (
+        <EuiLoadingElastic
+          className="appContainer__loading"
+          aria-label={i18n.translate('core.application.appContainer.loadingAriaLabel', {
+            defaultMessage: 'Loading application',
+          })}
+          size="xxl"
+        />
       )}
-      <div key={appId} ref={elementRef} />
+      <div className={APP_WRAPPER_CLASS} key={appId} ref={elementRef} aria-busy={showSpinner} />
     </Fragment>
   );
 };
diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts
index d4ab8f624f711..53428edf4b345 100644
--- a/src/core/public/doc_links/doc_links_service.ts
+++ b/src/core/public/doc_links/doc_links_service.ts
@@ -253,7 +253,7 @@ export class DocLinksService {
           guide: `${ELASTIC_WEBSITE_URL}guide/en/observability/${DOC_LINK_VERSION}/index.html`,
         },
         alerting: {
-          guide: `${KIBANA_DOCS}alert-management.html`,
+          guide: `${KIBANA_DOCS}create-and-manage-rules.html`,
           actionTypes: `${KIBANA_DOCS}action-types.html`,
           emailAction: `${KIBANA_DOCS}email-action-type.html`,
           emailActionConfig: `${KIBANA_DOCS}email-action-type.html`,
@@ -265,7 +265,7 @@ export class DocLinksService {
           preconfiguredConnectors: `${KIBANA_DOCS}pre-configured-connectors.html`,
           preconfiguredAlertHistoryConnector: `${KIBANA_DOCS}index-action-type.html#preconfigured-connector-alert-history`,
           serviceNowAction: `${KIBANA_DOCS}servicenow-action-type.html#configuring-servicenow`,
-          setupPrerequisites: `${KIBANA_DOCS}alerting-getting-started.html#alerting-setup-prerequisites`,
+          setupPrerequisites: `${KIBANA_DOCS}alerting-setup.html#alerting-prerequisites`,
           slackAction: `${KIBANA_DOCS}slack-action-type.html#configuring-slack`,
           teamsAction: `${KIBANA_DOCS}teams-action-type.html#configuring-teams`,
         },
diff --git a/src/core/public/rendering/_base.scss b/src/core/public/rendering/_base.scss
index 3a748f3ceb6fd..4bd6afe90d342 100644
--- a/src/core/public/rendering/_base.scss
+++ b/src/core/public/rendering/_base.scss
@@ -35,27 +35,12 @@
   position: relative; // This is temporary for apps that relied on this being present on `.application`
 }
 
-// TODO: This is problematic because it doesn't stay in line with EUI:
-// adapted from euiHeaderAffordForFixed as we need to handle the top banner
 @mixin kbnAffordForHeader($headerHeight) {
-  padding-top: $headerHeight;
+  @include euiHeaderAffordForFixed($headerHeight);
 
   #app-fixed-viewport {
     top: $headerHeight;
   }
-
-  .euiFlyout,
-  .euiCollapsibleNav {
-    top: $headerHeight;
-    height: calc(100% - #{$headerHeight});
-  }
-
-  @include euiBreakpoint('m', 'l', 'xl') {
-    .euiPageSideBar--sticky {
-      max-height: calc(100vh - #{$headerHeight});
-      top: #{$headerHeight};
-    }
-  }
 }
 
 .kbnBody {
diff --git a/src/core/server/http/lifecycle/on_pre_routing.ts b/src/core/server/http/lifecycle/on_pre_routing.ts
index dbd00df13707b..be0af8c118627 100644
--- a/src/core/server/http/lifecycle/on_pre_routing.ts
+++ b/src/core/server/http/lifecycle/on_pre_routing.ts
@@ -102,24 +102,7 @@ export function adoptToHapiOnRequest(fn: OnPreRoutingHandler, log: Logger) {
         appState.rewrittenUrl = appState.rewrittenUrl ?? request.url;
 
         const { url } = result;
-
-        // TODO: Remove once we upgrade to Node.js 12!
-        //
-        // Warning: The following for-loop took 10 days to write, and is a hack
-        // to force V8 to make a copy of the string in memory.
-        //
-        // The reason why we need this is because of what appears to be a bug
-        // in V8 that caused some URL paths to not be routed correctly once
-        // `request.setUrl` was called with the path.
-        //
-        // The details can be seen in this discussion on Twitter:
-        // https://twitter.com/wa7son/status/1319992632366518277
-        let urlCopy = '';
-        for (let i = 0; i < url.length; i++) {
-          urlCopy += url[i];
-        }
-
-        request.setUrl(urlCopy);
+        request.setUrl(url);
 
         // We should update raw request as well since it can be proxied to the old platform
         request.raw.req.url = url;
diff --git a/src/core/server/rendering/views/styles.tsx b/src/core/server/rendering/views/styles.tsx
index 105f94df9218f..fbeab4fb4388f 100644
--- a/src/core/server/rendering/views/styles.tsx
+++ b/src/core/server/rendering/views/styles.tsx
@@ -52,7 +52,6 @@ const InlineStyles: FC<{ darkMode: boolean }> = ({ darkMode }) => {
 
           .kbnWelcomeView {
             line-height: 1.5;
-            background-color: ${darkMode ? '#1D1E24' : '#FFF'};
             height: 100%;
             display: -webkit-box;
             display: -webkit-flex;
diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/archives/7.13.0_so_with_multiple_namespaces.zip b/src/core/server/saved_objects/migrationsv2/integration_tests/archives/7.13.0_so_with_multiple_namespaces.zip
deleted file mode 100644
index a92211c16c559..0000000000000
Binary files a/src/core/server/saved_objects/migrationsv2/integration_tests/archives/7.13.0_so_with_multiple_namespaces.zip and /dev/null differ
diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/archives/7.13.0_with_corrupted_so.zip b/src/core/server/saved_objects/migrationsv2/integration_tests/archives/7.13.0_with_corrupted_so.zip
index c6c89ac2879b2..44f2fc9ba19eb 100644
Binary files a/src/core/server/saved_objects/migrationsv2/integration_tests/archives/7.13.0_with_corrupted_so.zip and b/src/core/server/saved_objects/migrationsv2/integration_tests/archives/7.13.0_with_corrupted_so.zip differ
diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/archives/7.13.2_so_with_multiple_namespaces.zip b/src/core/server/saved_objects/migrationsv2/integration_tests/archives/7.13.2_so_with_multiple_namespaces.zip
new file mode 100644
index 0000000000000..e4dce85f15e38
Binary files /dev/null and b/src/core/server/saved_objects/migrationsv2/integration_tests/archives/7.13.2_so_with_multiple_namespaces.zip differ
diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/cleanup.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/cleanup.test.ts
index 91d86353b48fa..83d97555a4798 100644
--- a/src/core/server/saved_objects/migrationsv2/integration_tests/cleanup.test.ts
+++ b/src/core/server/saved_objects/migrationsv2/integration_tests/cleanup.test.ts
@@ -53,8 +53,7 @@ function createRoot() {
   );
 }
 
-// FAILING: https://github.com/elastic/kibana/issues/98352
-describe.skip('migration v2', () => {
+describe('migration v2', () => {
   let esServer: kbnTestServer.TestElasticsearchUtils;
   let root: Root;
 
@@ -78,7 +77,7 @@ describe.skip('migration v2', () => {
       adjustTimeout: (t: number) => jest.setTimeout(t),
       settings: {
         es: {
-          license: 'trial',
+          license: 'basic',
           // original SO:
           // {
           //   _index: '.kibana_7.13.0_001',
diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/rewriting_id.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/rewriting_id.test.ts
index 0f4085f6186be..759a9572d733b 100644
--- a/src/core/server/saved_objects/migrationsv2/integration_tests/rewriting_id.test.ts
+++ b/src/core/server/saved_objects/migrationsv2/integration_tests/rewriting_id.test.ts
@@ -89,7 +89,7 @@ function createRoot() {
 }
 
 // FAILING: https://github.com/elastic/kibana/issues/98351
-describe.skip('migration v2', () => {
+describe('migration v2', () => {
   let esServer: kbnTestServer.TestElasticsearchUtils;
   let root: Root;
 
@@ -114,7 +114,7 @@ describe.skip('migration v2', () => {
       adjustTimeout: (t: number) => jest.setTimeout(t),
       settings: {
         es: {
-          license: 'trial',
+          license: 'basic',
           // original SO:
           // [
           //   { id: 'foo:1', type: 'foo', foo: { name: 'Foo 1 default' } },
@@ -133,7 +133,7 @@ describe.skip('migration v2', () => {
           //     namespace: 'spacex',
           //   },
           // ];
-          dataArchive: Path.join(__dirname, 'archives', '7.13.0_so_with_multiple_namespaces.zip'),
+          dataArchive: Path.join(__dirname, 'archives', '7.13.2_so_with_multiple_namespaces.zip'),
         },
       },
     });
diff --git a/src/plugins/dashboard/server/usage/dashboard_telemetry.test.ts b/src/plugins/dashboard/server/usage/dashboard_telemetry.test.ts
index 1cfa9d862e6b9..60f1f7eb0955c 100644
--- a/src/plugins/dashboard/server/usage/dashboard_telemetry.test.ts
+++ b/src/plugins/dashboard/server/usage/dashboard_telemetry.test.ts
@@ -72,6 +72,22 @@ const lensXYSeriesB = ({
         visualization: {
           preferredSeriesType: 'seriesB',
         },
+        datasourceStates: {
+          indexpattern: {
+            layers: {
+              first: {
+                columns: {
+                  first: {
+                    operationType: 'terms',
+                  },
+                  second: {
+                    operationType: 'formula',
+                  },
+                },
+              },
+            },
+          },
+        },
       },
     },
   },
@@ -144,6 +160,7 @@ describe('dashboard telemetry', () => {
       expect(collectorData.lensByValue.a).toBe(3);
       expect(collectorData.lensByValue.seriesA).toBe(2);
       expect(collectorData.lensByValue.seriesB).toBe(1);
+      expect(collectorData.lensByValue.formula).toBe(1);
     });
 
     it('handles misshapen lens panels', () => {
diff --git a/src/plugins/dashboard/server/usage/dashboard_telemetry.ts b/src/plugins/dashboard/server/usage/dashboard_telemetry.ts
index 912dc04d16d09..fb1ddff469f57 100644
--- a/src/plugins/dashboard/server/usage/dashboard_telemetry.ts
+++ b/src/plugins/dashboard/server/usage/dashboard_telemetry.ts
@@ -27,6 +27,16 @@ interface LensPanel extends SavedDashboardPanel730ToLatest {
         visualization?: {
           preferredSeriesType?: string;
         };
+        datasourceStates?: {
+          indexpattern?: {
+            layers: Record<
+              string,
+              {
+                columns: Record<string, { operationType: string }>;
+              }
+            >;
+          };
+        };
       };
     };
   };
@@ -109,6 +119,19 @@ export const collectByValueLensInfo: DashboardCollectorFunction = (panels, colle
       }
 
       collectorData.lensByValue[type] = collectorData.lensByValue[type] + 1;
+
+      const hasFormula = Object.values(
+        lensPanel.embeddableConfig.attributes.state?.datasourceStates?.indexpattern?.layers || {}
+      ).some((layer) =>
+        Object.values(layer.columns).some((column) => column.operationType === 'formula')
+      );
+
+      if (hasFormula && !collectorData.lensByValue.formula) {
+        collectorData.lensByValue.formula = 0;
+      }
+      if (hasFormula) {
+        collectorData.lensByValue.formula++;
+      }
     }
   }
 };
diff --git a/src/plugins/data/common/field_formats/converters/duration.test.ts b/src/plugins/data/common/field_formats/converters/duration.test.ts
index 72551f4b7b236..9ea9919e757de 100644
--- a/src/plugins/data/common/field_formats/converters/duration.test.ts
+++ b/src/plugins/data/common/field_formats/converters/duration.test.ts
@@ -130,11 +130,11 @@ describe('Duration Format', () => {
     fixtures: [
       {
         input: -60,
-        output: '-60 Seconds',
+        output: '-60 seconds',
       },
       {
         input: -32.333,
-        output: '-32 Seconds',
+        output: '-32 seconds',
       },
     ],
   });
@@ -147,15 +147,15 @@ describe('Duration Format', () => {
     fixtures: [
       {
         input: 1988,
-        output: '0.00 Milliseconds',
+        output: '0.00 milliseconds',
       },
       {
         input: 658,
-        output: '0.00 Milliseconds',
+        output: '0.00 milliseconds',
       },
       {
         input: 3857,
-        output: '0.00 Milliseconds',
+        output: '0.00 milliseconds',
       },
     ],
   });
@@ -168,15 +168,15 @@ describe('Duration Format', () => {
     fixtures: [
       {
         input: 1988,
-        output: '1.99 Milliseconds',
+        output: '1.99 milliseconds',
       },
       {
         input: 658,
-        output: '0.66 Milliseconds',
+        output: '0.66 milliseconds',
       },
       {
         input: 3857,
-        output: '3.86 Milliseconds',
+        output: '3.86 milliseconds',
       },
     ],
   });
@@ -189,19 +189,19 @@ describe('Duration Format', () => {
     fixtures: [
       {
         input: 1988,
-        output: '2.0 Milliseconds',
+        output: '2.0 milliseconds',
       },
       {
         input: 0,
-        output: '0.0 Milliseconds',
+        output: '0.0 milliseconds',
       },
       {
         input: 658,
-        output: '0.7 Milliseconds',
+        output: '0.7 milliseconds',
       },
       {
         input: 3857,
-        output: '3.9 Milliseconds',
+        output: '3.9 milliseconds',
       },
     ],
   });
@@ -214,15 +214,15 @@ describe('Duration Format', () => {
     fixtures: [
       {
         input: 600,
-        output: '10 Minutes',
+        output: '10 minutes',
       },
       {
         input: 30,
-        output: '30 Seconds',
+        output: '30 seconds',
       },
       {
         input: 3000,
-        output: '50 Minutes',
+        output: '50 minutes',
       },
     ],
   });
diff --git a/src/plugins/data/common/field_formats/converters/duration.ts b/src/plugins/data/common/field_formats/converters/duration.ts
index c9a7091db8471..71ac022ba5e5c 100644
--- a/src/plugins/data/common/field_formats/converters/duration.ts
+++ b/src/plugins/data/common/field_formats/converters/duration.ts
@@ -263,7 +263,7 @@ export class DurationFormat extends FieldFormat {
     const precise = human || humanPrecise ? formatted : formatted.toFixed(outputPrecision);
     const type = outputFormats.find(({ method }) => method === outputFormat);
 
-    const unitText = useShortSuffix ? type?.shortText : type?.text;
+    const unitText = useShortSuffix ? type?.shortText : type?.text.toLowerCase();
 
     const suffix = showSuffix && unitText && !human ? `${includeSpace}${unitText}` : '';
 
@@ -294,7 +294,7 @@ function formatDuration(
 
   const getUnitText = (method: string) => {
     const type = outputFormats.find(({ method: methodT }) => method === methodT);
-    return useShortSuffix ? type?.shortText : type?.text;
+    return useShortSuffix ? type?.shortText : type?.text.toLowerCase();
   };
 
   for (let i = 0; i < units.length; i++) {
diff --git a/src/plugins/discover/public/application/angular/create_discover_grid_directive.tsx b/src/plugins/discover/public/application/angular/create_discover_grid_directive.tsx
index 1fc8edcb4d065..810be94ce24b0 100644
--- a/src/plugins/discover/public/application/angular/create_discover_grid_directive.tsx
+++ b/src/plugins/discover/public/application/angular/create_discover_grid_directive.tsx
@@ -51,5 +51,6 @@ export function createDiscoverGridDirective(reactDirective: any) {
     ['settings', { watchDepth: 'reference' }],
     ['showTimeCol', { watchDepth: 'value' }],
     ['sort', { watchDepth: 'value' }],
+    ['className', { watchDepth: 'value' }],
   ]);
 }
diff --git a/src/plugins/discover/public/application/angular/doc_table/create_doc_table_embeddable.tsx b/src/plugins/discover/public/application/angular/doc_table/create_doc_table_embeddable.tsx
new file mode 100644
index 0000000000000..19913ed6de870
--- /dev/null
+++ b/src/plugins/discover/public/application/angular/doc_table/create_doc_table_embeddable.tsx
@@ -0,0 +1,85 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React, { useRef, useEffect } from 'react';
+import { I18nProvider } from '@kbn/i18n/react';
+import { IScope } from 'angular';
+import { getServices } from '../../../kibana_services';
+import { DocTableLegacyProps, injectAngularElement } from './create_doc_table_react';
+
+type AngularEmbeddableScope = IScope & { renderProps?: DocTableEmbeddableProps };
+
+export interface DocTableEmbeddableProps extends Partial<DocTableLegacyProps> {
+  refs: HTMLElement;
+}
+
+function getRenderFn(domNode: Element, props: DocTableEmbeddableProps) {
+  const directive = {
+    template: `<doc-table
+        class="panel-content"
+        columns="renderProps.columns"
+        data-description="{{renderProps.searchDescription}}"
+        data-shared-item
+        data-test-subj="embeddedSavedSearchDocTable"
+        data-title="{{renderProps.sharedItemTitle}}"
+        filter="renderProps.onFilter"
+        hits="renderProps.rows"
+        index-pattern="renderProps.indexPattern"
+        is-loading="renderProps.isLoading"
+        on-add-column="renderProps.onAddColumn"
+        on-change-sort-order="renderProps.onSort"
+        on-move-column="renderProps.onMoveColumn"
+        on-remove-column="renderProps.onRemoveColumn"
+        render-complete
+        sorting="renderProps.sort"
+        total-hit-count="renderProps.totalHitCount"
+        use-new-fields-api="renderProps.useNewFieldsApi"></doc-table>`,
+  };
+
+  return async () => {
+    try {
+      const injector = await getServices().getEmbeddableInjector();
+      return await injectAngularElement(domNode, directive.template, props, injector);
+    } catch (e) {
+      // eslint-disable-next-line no-console
+      console.error(e);
+      throw e;
+    }
+  };
+}
+
+export function DiscoverDocTableEmbeddable(props: DocTableEmbeddableProps) {
+  return (
+    <I18nProvider>
+      <DocTableLegacyInner {...props} />
+    </I18nProvider>
+  );
+}
+
+function DocTableLegacyInner(renderProps: DocTableEmbeddableProps) {
+  const scope = useRef<AngularEmbeddableScope | undefined>();
+
+  useEffect(() => {
+    if (renderProps.refs && !scope.current) {
+      const fn = getRenderFn(renderProps.refs, renderProps);
+      fn().then((newScope) => {
+        scope.current = newScope;
+      });
+    } else if (scope?.current) {
+      scope.current.renderProps = { ...renderProps };
+      scope.current.$applyAsync();
+    }
+  }, [renderProps]);
+
+  useEffect(() => {
+    return () => {
+      scope.current?.$destroy();
+    };
+  }, []);
+  return <React.Fragment />;
+}
diff --git a/src/plugins/discover/public/application/angular/doc_table/index.ts b/src/plugins/discover/public/application/angular/doc_table/index.ts
index 2aaf5a8bda7b6..3a8f170f8680d 100644
--- a/src/plugins/discover/public/application/angular/doc_table/index.ts
+++ b/src/plugins/discover/public/application/angular/doc_table/index.ts
@@ -9,3 +9,4 @@
 export { createDocTableDirective } from './doc_table';
 export { getSort, getSortArray } from './lib/get_sort';
 export { getSortForSearchSource } from './lib/get_sort_for_search_source';
+export { getDefaultSort } from './lib/get_default_sort';
diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx
index 65a6ee80564e9..f1c56b7a57195 100644
--- a/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx
+++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx
@@ -51,6 +51,10 @@ export interface DiscoverGridProps {
    * Determines which element labels the grid for ARIA
    */
   ariaLabelledBy: string;
+  /**
+   * Optional class name to apply
+   */
+  className?: string;
   /**
    * Determines which columns are displayed
    */
@@ -175,6 +179,7 @@ export const DiscoverGrid = ({
   isSortEnabled = true,
   isPaginationEnabled = true,
   controlColumnIds = ['openDetails', 'select'],
+  className,
 }: DiscoverGridProps) => {
   const [selectedDocs, setSelectedDocs] = useState<string[]>([]);
   const [isFilterActive, setIsFilterActive] = useState(false);
@@ -284,6 +289,7 @@ export const DiscoverGrid = ({
       ),
     [displayedColumns, indexPattern, showTimeCol, settings, defaultColumns, isSortEnabled]
   );
+
   const schemaDetectors = useMemo(() => getSchemaDetectors(), []);
   const columnsVisibility = useMemo(
     () => ({
@@ -368,6 +374,7 @@ export const DiscoverGrid = ({
         data-title={searchTitle}
         data-description={searchDescription}
         data-document-number={displayedRows.length}
+        className={className}
       >
         <KibanaContextProvider services={{ uiSettings: services.uiSettings }}>
           <EuiDataGridMemoized
diff --git a/src/plugins/discover/public/application/embeddable/search_embeddable.ts b/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx
similarity index 54%
rename from src/plugins/discover/public/application/embeddable/search_embeddable.ts
rename to src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx
index 1e3c7e77d3615..c885cb92e7649 100644
--- a/src/plugins/discover/public/application/embeddable/search_embeddable.ts
+++ b/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx
@@ -6,68 +6,57 @@
  * Side Public License, v 1.
  */
 
-import './search_embeddable.scss';
-import angular from 'angular';
-import _ from 'lodash';
 import { Subscription } from 'rxjs';
+import React from 'react';
+import ReactDOM from 'react-dom';
 import { i18n } from '@kbn/i18n';
-import { UiActionsStart } from '../../../../ui_actions/public';
-import { RequestAdapter, Adapters } from '../../../../inspector/public';
+import { isEqual } from 'lodash';
+import { Container, Embeddable } from '../../../../embeddable/public';
+import { ISearchEmbeddable, SearchInput, SearchOutput } from './types';
+import { SavedSearch } from '../../saved_searches';
+import { Adapters, RequestAdapter } from '../../../../inspector/common';
+import { SEARCH_EMBEDDABLE_TYPE } from './constants';
+import { APPLY_FILTER_TRIGGER, esFilters, FilterManager } from '../../../../data/public';
+import { DiscoverServices } from '../../build_services';
 import {
-  APPLY_FILTER_TRIGGER,
-  esFilters,
-  Filter,
-  TimeRange,
-  FilterManager,
   Query,
+  TimeRange,
+  Filter,
   IFieldType,
-} from '../../../../data/public';
-import { Container, Embeddable } from '../../../../embeddable/public';
-import * as columnActions from '../angular/doc_table/actions/columns';
-import searchTemplate from './search_template.html';
-import searchTemplateGrid from './search_template_datagrid.html';
-import { ISearchEmbeddable, SearchInput, SearchOutput } from './types';
+  IndexPattern,
+  ISearchSource,
+} from '../../../../data/common';
 import { SortOrder } from '../angular/doc_table/components/table_header/helpers';
-import { getSortForSearchSource } from '../angular/doc_table';
-import { getServices, IndexPattern, ISearchSource } from '../../kibana_services';
-import { SEARCH_EMBEDDABLE_TYPE } from './constants';
-import { SavedSearch } from '../..';
+import { ElasticSearchHit } from '../doc_views/doc_views_types';
+import { SavedSearchEmbeddableComponent } from './saved_search_embeddable_component';
+import { UiActionsStart } from '../../../../ui_actions/public';
+import { getServices } from '../../kibana_services';
 import {
   DOC_HIDE_TIME_COLUMN_SETTING,
+  DOC_TABLE_LEGACY,
   SAMPLE_SIZE_SETTING,
   SEARCH_FIELDS_FROM_SOURCE,
   SORT_DEFAULT_ORDER_SETTING,
 } from '../../../common';
-import { DiscoverGridSettings } from '../components/discover_grid/types';
-import { DiscoverServices } from '../../build_services';
-import { ElasticSearchHit } from '../doc_views/doc_views_types';
-import { getDefaultSort } from '../angular/doc_table/lib/get_default_sort';
+import * as columnActions from '../angular/doc_table/actions/columns';
+import { getSortForSearchSource, getDefaultSort } from '../angular/doc_table';
 import { handleSourceColumnState } from '../angular/helpers';
+import { DiscoverGridProps } from '../components/discover_grid/discover_grid';
+import { DiscoverGridSettings } from '../components/discover_grid/types';
 
-interface SearchScope extends ng.IScope {
-  columns?: string[];
+export interface SearchProps extends Partial<DiscoverGridProps> {
   settings?: DiscoverGridSettings;
   description?: string;
-  sort?: SortOrder[];
   sharedItemTitle?: string;
   inspectorAdapters?: Adapters;
-  setSortOrder?: (sortPair: SortOrder[]) => void;
-  setColumns?: (columns: string[]) => void;
-  removeColumn?: (column: string) => void;
-  addColumn?: (column: string) => void;
-  moveColumn?: (column: string, index: number) => void;
+
   filter?: (field: IFieldType, value: string[], operator: string) => void;
   hits?: ElasticSearchHit[];
-  indexPattern?: IndexPattern;
   totalHitCount?: number;
-  isLoading?: boolean;
-  showTimeCol?: boolean;
-  useNewFieldsApi?: boolean;
+  onMoveColumn?: (column: string, index: number) => void;
 }
 
 interface SearchEmbeddableConfig {
-  $rootScope: ng.IRootScopeService;
-  $compile: ng.ICompileService;
   savedSearch: SavedSearch;
   editUrl: string;
   editPath: string;
@@ -77,17 +66,13 @@ interface SearchEmbeddableConfig {
   services: DiscoverServices;
 }
 
-export class SearchEmbeddable
+export class SavedSearchEmbeddable
   extends Embeddable<SearchInput, SearchOutput>
   implements ISearchEmbeddable {
   private readonly savedSearch: SavedSearch;
-  private $rootScope: ng.IRootScopeService;
-  private $compile: ng.ICompileService;
   private inspectorAdapters: Adapters;
-  private searchScope?: SearchScope;
   private panelTitle: string = '';
-  private filtersSearchSource?: ISearchSource;
-  private searchInstance?: JQLite;
+  private filtersSearchSource!: ISearchSource;
   private subscription?: Subscription;
   public readonly type = SEARCH_EMBEDDABLE_TYPE;
   private filterManager: FilterManager;
@@ -98,11 +83,12 @@ export class SearchEmbeddable
   private prevFilters?: Filter[];
   private prevQuery?: Query;
   private prevSearchSessionId?: string;
+  private searchProps?: SearchProps;
+
+  private node?: HTMLElement;
 
   constructor(
     {
-      $rootScope,
-      $compile,
       savedSearch,
       editUrl,
       editPath,
@@ -130,164 +116,24 @@ export class SearchEmbeddable
     this.services = services;
     this.filterManager = filterManager;
     this.savedSearch = savedSearch;
-    this.$rootScope = $rootScope;
-    this.$compile = $compile;
     this.inspectorAdapters = {
       requests: new RequestAdapter(),
     };
-    this.initializeSearchScope();
+    this.initializeSearchEmbeddableProps();
 
     this.subscription = this.getUpdated$().subscribe(() => {
       this.panelTitle = this.output.title || '';
 
-      if (this.searchScope) {
-        this.pushContainerStateParamsToScope(this.searchScope);
+      if (this.searchProps) {
+        this.pushContainerStateParamsToProps(this.searchProps);
       }
     });
   }
 
-  public getInspectorAdapters() {
-    return this.inspectorAdapters;
-  }
-
-  public getSavedSearch() {
-    return this.savedSearch;
-  }
-
-  /**
-   *
-   * @param {Element} domNode
-   */
-  public render(domNode: HTMLElement) {
-    if (!this.searchScope) {
-      throw new Error('Search scope not defined');
-    }
-    this.searchInstance = this.$compile(
-      this.services.uiSettings.get('doc_table:legacy') ? searchTemplate : searchTemplateGrid
-    )(this.searchScope);
-    const rootNode = angular.element(domNode);
-    rootNode.append(this.searchInstance);
-
-    this.pushContainerStateParamsToScope(this.searchScope);
-  }
-
-  public destroy() {
-    super.destroy();
-    this.savedSearch.destroy();
-    if (this.searchInstance) {
-      this.searchInstance.remove();
-    }
-    if (this.searchScope) {
-      this.searchScope.$destroy();
-      delete this.searchScope;
-    }
-    if (this.subscription) {
-      this.subscription.unsubscribe();
-    }
-
-    if (this.abortController) this.abortController.abort();
-  }
-
-  private initializeSearchScope() {
-    const searchScope: SearchScope = (this.searchScope = this.$rootScope.$new());
-
-    searchScope.description = this.savedSearch.description;
-    searchScope.inspectorAdapters = this.inspectorAdapters;
-
-    const { searchSource } = this.savedSearch;
-    const indexPattern = (searchScope.indexPattern = searchSource.getField('index'))!;
-
-    if (!this.savedSearch.sort || !this.savedSearch.sort.length) {
-      this.savedSearch.sort = getDefaultSort(
-        indexPattern,
-        getServices().uiSettings.get(SORT_DEFAULT_ORDER_SETTING, 'desc')
-      );
-    }
-
-    const timeRangeSearchSource = searchSource.create();
-    timeRangeSearchSource.setField('filter', () => {
-      if (!this.searchScope || !this.input.timeRange) return;
-      return this.services.timefilter.createFilter(indexPattern, this.input.timeRange);
-    });
-
-    this.filtersSearchSource = searchSource.create();
-    this.filtersSearchSource.setParent(timeRangeSearchSource);
-
-    searchSource.setParent(this.filtersSearchSource);
-
-    this.pushContainerStateParamsToScope(searchScope);
-
-    searchScope.setSortOrder = (sort) => {
-      this.updateInput({ sort });
-    };
-
-    searchScope.isLoading = true;
-
-    const useNewFieldsApi = !getServices().uiSettings.get(SEARCH_FIELDS_FROM_SOURCE, false);
-    searchScope.useNewFieldsApi = useNewFieldsApi;
-
-    searchScope.addColumn = (columnName: string) => {
-      if (!searchScope.columns) {
-        return;
-      }
-      const columns = columnActions.addColumn(searchScope.columns, columnName, useNewFieldsApi);
-      this.updateInput({ columns });
-    };
-
-    searchScope.removeColumn = (columnName: string) => {
-      if (!searchScope.columns) {
-        return;
-      }
-      const columns = columnActions.removeColumn(searchScope.columns, columnName, useNewFieldsApi);
-      this.updateInput({ columns });
-    };
-
-    searchScope.moveColumn = (columnName, newIndex: number) => {
-      if (!searchScope.columns) {
-        return;
-      }
-      const columns = columnActions.moveColumn(searchScope.columns, columnName, newIndex);
-      this.updateInput({ columns });
-    };
-
-    searchScope.setColumns = (columns: string[]) => {
-      this.updateInput({ columns });
-    };
-
-    if (this.savedSearch.grid) {
-      searchScope.settings = this.savedSearch.grid;
-    }
-    searchScope.showTimeCol = !this.services.uiSettings.get(DOC_HIDE_TIME_COLUMN_SETTING, false);
-
-    searchScope.filter = async (field, value, operator) => {
-      let filters = esFilters.generateFilters(
-        this.filterManager,
-        field,
-        value,
-        operator,
-        indexPattern.id!
-      );
-      filters = filters.map((filter) => ({
-        ...filter,
-        $state: { store: esFilters.FilterStateStore.APP_STATE },
-      }));
-
-      await this.executeTriggerActions(APPLY_FILTER_TRIGGER, {
-        embeddable: this,
-        filters,
-      });
-    };
-  }
-
-  public reload() {
-    if (this.searchScope)
-      this.pushContainerStateParamsToScope(this.searchScope, { forceFetch: true });
-  }
-
   private fetch = async () => {
     const searchSessionId = this.input.searchSessionId;
     const useNewFieldsApi = !this.services.uiSettings.get(SEARCH_FIELDS_FROM_SOURCE, false);
-    if (!this.searchScope) return;
+    if (!this.searchProps) return;
 
     const { searchSource } = this.savedSearch;
 
@@ -299,8 +145,8 @@ export class SearchEmbeddable
     searchSource.setField(
       'sort',
       getSortForSearchSource(
-        this.searchScope.sort,
-        this.searchScope.indexPattern,
+        this.searchProps!.sort,
+        this.searchProps!.indexPattern,
         this.services.uiSettings.get(SORT_DEFAULT_ORDER_SETTING)
       )
     );
@@ -310,8 +156,8 @@ export class SearchEmbeddable
       searchSource.setField('fields', [fields]);
     } else {
       searchSource.removeField('fields');
-      if (this.searchScope.indexPattern) {
-        const fieldNames = this.searchScope.indexPattern.fields.map((field) => field.name);
+      if (this.searchProps.indexPattern) {
+        const fieldNames = this.searchProps.indexPattern.fields.map((field) => field.name);
         searchSource.setField('fieldsFromSource', fieldNames);
       }
     }
@@ -319,9 +165,8 @@ export class SearchEmbeddable
     // Log request to inspector
     this.inspectorAdapters.requests!.reset();
 
-    this.searchScope.$apply(() => {
-      this.searchScope!.isLoading = true;
-    });
+    this.searchProps!.isLoading = true;
+
     this.updateOutput({ loading: true, error: undefined });
 
     try {
@@ -344,64 +189,222 @@ export class SearchEmbeddable
         .toPromise();
       this.updateOutput({ loading: false, error: undefined });
 
-      // Apply the changes to the angular scope
-      this.searchScope.$apply(() => {
-        this.searchScope!.hits = resp.hits.hits;
-        this.searchScope!.totalHitCount = resp.hits.total as number;
-        this.searchScope!.isLoading = false;
-      });
+      this.searchProps!.rows = resp.hits.hits;
+      this.searchProps!.totalHitCount = resp.hits.total as number;
+      this.searchProps!.isLoading = false;
     } catch (error) {
       this.updateOutput({ loading: false, error });
-      this.searchScope.$apply(() => {
-        this.searchScope!.isLoading = false;
-      });
+
+      this.searchProps!.isLoading = false;
     }
   };
 
-  private pushContainerStateParamsToScope(
-    searchScope: SearchScope,
+  private initializeSearchEmbeddableProps() {
+    const { searchSource } = this.savedSearch;
+
+    const indexPattern = searchSource.getField('index');
+
+    if (!indexPattern) {
+      return;
+    }
+
+    if (!this.savedSearch.sort || !this.savedSearch.sort.length) {
+      this.savedSearch.sort = getDefaultSort(
+        indexPattern,
+        getServices().uiSettings.get(SORT_DEFAULT_ORDER_SETTING, 'desc')
+      );
+    }
+
+    const props: SearchProps = {
+      columns: this.savedSearch.columns,
+      indexPattern,
+      isLoading: false,
+      sort: getDefaultSort(
+        indexPattern,
+        getServices().uiSettings.get(SORT_DEFAULT_ORDER_SETTING, 'desc')
+      ),
+      rows: [],
+      searchDescription: this.savedSearch.description,
+      description: this.savedSearch.description,
+      inspectorAdapters: this.inspectorAdapters,
+      searchTitle: this.savedSearch.lastSavedTitle,
+      services: this.services,
+      onAddColumn: (columnName: string) => {
+        if (!props.columns) {
+          return;
+        }
+        const updatedColumns = columnActions.addColumn(props.columns, columnName, true);
+        this.updateInput({ columns: updatedColumns });
+      },
+      onRemoveColumn: (columnName: string) => {
+        if (!props.columns) {
+          return;
+        }
+        const updatedColumns = columnActions.removeColumn(props.columns, columnName, true);
+        this.updateInput({ columns: updatedColumns });
+      },
+      onMoveColumn: (columnName: string, newIndex: number) => {
+        if (!props.columns) {
+          return;
+        }
+        const columns = columnActions.moveColumn(props.columns, columnName, newIndex);
+        this.updateInput({ columns });
+      },
+      onSetColumns: (columns: string[]) => {
+        this.updateInput({ columns });
+      },
+      onSort: (sort: string[][]) => {
+        const sortOrderArr: SortOrder[] = [];
+        sort.forEach((arr) => {
+          sortOrderArr.push(arr as SortOrder);
+        });
+        this.updateInput({ sort: sortOrderArr });
+      },
+      sampleSize: 500,
+      onFilter: async (field, value, operator) => {
+        let filters = esFilters.generateFilters(
+          this.filterManager,
+          // @ts-expect-error
+          field,
+          value,
+          operator,
+          indexPattern.id!
+        );
+        filters = filters.map((filter) => ({
+          ...filter,
+          $state: { store: esFilters.FilterStateStore.APP_STATE },
+        }));
+
+        await this.executeTriggerActions(APPLY_FILTER_TRIGGER, {
+          embeddable: this,
+          filters,
+        });
+      },
+      useNewFieldsApi: !this.services.uiSettings.get(SEARCH_FIELDS_FROM_SOURCE, false),
+      showTimeCol: !this.services.uiSettings.get(DOC_HIDE_TIME_COLUMN_SETTING, false),
+      ariaLabelledBy: 'documentsAriaLabel',
+    };
+
+    const timeRangeSearchSource = searchSource.create();
+    timeRangeSearchSource.setField('filter', () => {
+      if (!this.searchProps || !this.input.timeRange) return;
+      return this.services.timefilter.createFilter(indexPattern, this.input.timeRange);
+    });
+
+    this.filtersSearchSource = searchSource.create();
+    this.filtersSearchSource.setParent(timeRangeSearchSource);
+
+    searchSource.setParent(this.filtersSearchSource);
+
+    this.pushContainerStateParamsToProps(props);
+
+    props.isLoading = true;
+
+    if (this.savedSearch.grid) {
+      props.settings = this.savedSearch.grid;
+    }
+  }
+
+  private async pushContainerStateParamsToProps(
+    searchProps: SearchProps,
     { forceFetch = false }: { forceFetch: boolean } = { forceFetch: false }
   ) {
     const isFetchRequired =
       !esFilters.onlyDisabledFiltersChanged(this.input.filters, this.prevFilters) ||
-      !_.isEqual(this.prevQuery, this.input.query) ||
-      !_.isEqual(this.prevTimeRange, this.input.timeRange) ||
-      !_.isEqual(searchScope.sort, this.input.sort || this.savedSearch.sort) ||
+      !isEqual(this.prevQuery, this.input.query) ||
+      !isEqual(this.prevTimeRange, this.input.timeRange) ||
+      !isEqual(searchProps.sort, this.input.sort || this.savedSearch.sort) ||
       this.prevSearchSessionId !== this.input.searchSessionId;
 
     // If there is column or sort data on the panel, that means the original columns or sort settings have
     // been overridden in a dashboard.
-    searchScope.columns = handleSourceColumnState(
+    searchProps.columns = handleSourceColumnState(
       { columns: this.input.columns || this.savedSearch.columns },
       this.services.core.uiSettings
     ).columns;
+
     const savedSearchSort =
       this.savedSearch.sort && this.savedSearch.sort.length
         ? this.savedSearch.sort
         : getDefaultSort(
-            this.searchScope?.indexPattern,
+            this.searchProps?.indexPattern,
             getServices().uiSettings.get(SORT_DEFAULT_ORDER_SETTING, 'desc')
           );
-    searchScope.sort = this.input.sort || savedSearchSort;
-    searchScope.sharedItemTitle = this.panelTitle;
-
+    searchProps.sort = this.input.sort || savedSearchSort;
+    searchProps.sharedItemTitle = this.panelTitle;
     if (forceFetch || isFetchRequired) {
-      this.filtersSearchSource!.setField('filter', this.input.filters);
-      this.filtersSearchSource!.setField('query', this.input.query);
+      this.filtersSearchSource.setField('filter', this.input.filters);
+      this.filtersSearchSource.setField('query', this.input.query);
       if (this.input.query?.query || this.input.filters?.length) {
-        this.filtersSearchSource!.setField('highlightAll', true);
+        this.filtersSearchSource.setField('highlightAll', true);
       } else {
-        this.filtersSearchSource!.removeField('highlightAll');
+        this.filtersSearchSource.removeField('highlightAll');
       }
 
       this.prevFilters = this.input.filters;
       this.prevQuery = this.input.query;
       this.prevTimeRange = this.input.timeRange;
       this.prevSearchSessionId = this.input.searchSessionId;
-      this.fetch();
-    } else if (this.searchScope) {
-      // trigger a digest cycle to make sure non-fetch relevant changes are propagated
-      this.searchScope.$applyAsync();
+      this.searchProps = searchProps;
+      await this.fetch();
+    } else if (this.searchProps && this.node) {
+      this.searchProps = searchProps;
+    }
+
+    if (this.node) {
+      this.renderReactComponent(this.node, this.searchProps!);
+    }
+  }
+
+  /**
+   *
+   * @param {Element} domNode
+   */
+  public async render(domNode: HTMLElement) {
+    if (!this.searchProps) {
+      throw new Error('Search props not defined');
+    }
+    if (this.node) {
+      ReactDOM.unmountComponentAtNode(this.node);
+    }
+    this.node = domNode;
+  }
+
+  private renderReactComponent(domNode: HTMLElement, searchProps: SearchProps) {
+    if (!this.searchProps) {
+      return;
+    }
+    const useLegacyTable = this.services.uiSettings.get(DOC_TABLE_LEGACY);
+    const props = {
+      searchProps,
+      useLegacyTable,
+      refs: domNode,
+    };
+    ReactDOM.render(<SavedSearchEmbeddableComponent {...props} />, domNode);
+  }
+
+  public reload() {
+    if (this.searchProps) {
+      this.pushContainerStateParamsToProps(this.searchProps, { forceFetch: true });
     }
   }
+
+  public getSavedSearch(): SavedSearch {
+    return this.savedSearch;
+  }
+
+  public getInspectorAdapters() {
+    return this.inspectorAdapters;
+  }
+
+  public destroy() {
+    super.destroy();
+    this.savedSearch.destroy();
+    if (this.searchProps) {
+      delete this.searchProps;
+    }
+    this.subscription?.unsubscribe();
+
+    if (this.abortController) this.abortController.abort();
+  }
 }
diff --git a/src/plugins/discover/public/application/embeddable/saved_search_embeddable_component.tsx b/src/plugins/discover/public/application/embeddable/saved_search_embeddable_component.tsx
new file mode 100644
index 0000000000000..5b2a2635d04bd
--- /dev/null
+++ b/src/plugins/discover/public/application/embeddable/saved_search_embeddable_component.tsx
@@ -0,0 +1,39 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React from 'react';
+
+import { DiscoverGridEmbeddable } from '../angular/create_discover_grid_directive';
+import { DiscoverDocTableEmbeddable } from '../angular/doc_table/create_doc_table_embeddable';
+import { DiscoverGridProps } from '../components/discover_grid/discover_grid';
+import { SearchProps } from './saved_search_embeddable';
+
+interface SavedSearchEmbeddableComponentProps {
+  searchProps: SearchProps;
+  useLegacyTable: boolean;
+  refs: HTMLElement;
+}
+
+const DiscoverDocTableEmbeddableMemoized = React.memo(DiscoverDocTableEmbeddable);
+const DiscoverGridEmbeddableMemoized = React.memo(DiscoverGridEmbeddable);
+
+export function SavedSearchEmbeddableComponent({
+  searchProps,
+  useLegacyTable,
+  refs,
+}: SavedSearchEmbeddableComponentProps) {
+  if (useLegacyTable) {
+    const docTableProps = {
+      ...searchProps,
+      refs,
+    };
+    return <DiscoverDocTableEmbeddableMemoized {...docTableProps} />;
+  }
+  const discoverGridProps = searchProps as DiscoverGridProps;
+  return <DiscoverGridEmbeddableMemoized {...discoverGridProps} className="dscDiscoverGrid" />;
+}
diff --git a/src/plugins/discover/public/application/embeddable/search_embeddable_factory.ts b/src/plugins/discover/public/application/embeddable/search_embeddable_factory.ts
index 77da138d118dd..360844976284e 100644
--- a/src/plugins/discover/public/application/embeddable/search_embeddable_factory.ts
+++ b/src/plugins/discover/public/application/embeddable/search_embeddable_factory.ts
@@ -18,8 +18,9 @@ import {
 
 import { TimeRange } from '../../../../data/public';
 
-import { SearchInput, SearchOutput, SearchEmbeddable } from './types';
+import { SearchInput, SearchOutput } from './types';
 import { SEARCH_EMBEDDABLE_TYPE } from './constants';
+import { SavedSearchEmbeddable } from './saved_search_embeddable';
 
 interface StartServices {
   executeTriggerActions: UiActionsStart['executeTriggerActions'];
@@ -27,7 +28,7 @@ interface StartServices {
 }
 
 export class SearchEmbeddableFactory
-  implements EmbeddableFactoryDefinition<SearchInput, SearchOutput, SearchEmbeddable> {
+  implements EmbeddableFactoryDefinition<SearchInput, SearchOutput, SavedSearchEmbeddable> {
   public readonly type = SEARCH_EMBEDDABLE_TYPE;
   private $injector: auto.IInjectorService | null;
   private getInjector: () => Promise<auto.IInjectorService> | null;
@@ -65,14 +66,11 @@ export class SearchEmbeddableFactory
     savedObjectId: string,
     input: Partial<SearchInput> & { id: string; timeRange: TimeRange },
     parent?: Container
-  ): Promise<SearchEmbeddable | ErrorEmbeddable> => {
+  ): Promise<SavedSearchEmbeddable | ErrorEmbeddable> => {
     if (!this.$injector) {
       this.$injector = await this.getInjector();
     }
-    const $injector = this.$injector as auto.IInjectorService;
 
-    const $compile = $injector.get<ng.ICompileService>('$compile');
-    const $rootScope = $injector.get<ng.IRootScopeService>('$rootScope');
     const filterManager = getServices().filterManager;
 
     const url = await getServices().getSavedSearchUrlById(savedObjectId);
@@ -81,12 +79,12 @@ export class SearchEmbeddableFactory
       const savedObject = await getServices().getSavedSearchById(savedObjectId);
       const indexPattern = savedObject.searchSource.getField('index');
       const { executeTriggerActions } = await this.getStartServices();
-      const { SearchEmbeddable: SearchEmbeddableClass } = await import('./search_embeddable');
-      return new SearchEmbeddableClass(
+      const { SavedSearchEmbeddable: SavedSearchEmbeddableClass } = await import(
+        './saved_search_embeddable'
+      );
+      return new SavedSearchEmbeddableClass(
         {
           savedSearch: savedObject,
-          $rootScope,
-          $compile,
           editUrl,
           editPath: url,
           filterManager,
diff --git a/src/plugins/discover/public/application/embeddable/search_template.html b/src/plugins/discover/public/application/embeddable/search_template.html
deleted file mode 100644
index 3e37b3645650f..0000000000000
--- a/src/plugins/discover/public/application/embeddable/search_template.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<doc-table
-  class="panel-content"
-  columns="columns"
-  data-description="{{description}}"
-  data-shared-item
-  data-test-subj="embeddedSavedSearchDocTable"
-  data-title="{{sharedItemTitle}}"
-  filter="filter"
-  hits="hits"
-  index-pattern="indexPattern"
-  is-loading="isLoading"
-  on-add-column="addColumn"
-  on-change-sort-order="setSortOrder"
-  on-move-column="moveColumn"
-  on-remove-column="removeColumn"
-  render-complete
-  sorting="sort"
-  total-hit-count="totalHitCount"
-  use-new-fields-api="useNewFieldsApi"
->
-</doc-table>
diff --git a/src/plugins/discover/public/application/embeddable/search_template_datagrid.html b/src/plugins/discover/public/application/embeddable/search_template_datagrid.html
deleted file mode 100644
index 8ad7938350d9c..0000000000000
--- a/src/plugins/discover/public/application/embeddable/search_template_datagrid.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<discover-grid
-  class="dscDiscoverGrid"
-  columns="columns"
-  search-description="description"
-  search-title="sharedItemTitle"
-  data-test-subj="embeddedSavedSearchDocTable"
-  index-pattern="indexPattern"
-  is-loading="isLoading"
-  on-add-column="addColumn"
-  on-filter="filter"
-  on-remove-column="removeColumn"
-  on-set-columns="setColumns"
-  on-sort="setSortOrder"
-  rows="hits"
-  sample-size="500"
-  settings="settings"
-  show-time-col="showTimeCol"
-  sort="sort"
-></discover-grid>
diff --git a/src/plugins/expressions/common/executor/executor.test.ts b/src/plugins/expressions/common/executor/executor.test.ts
index 6175c9e170a90..3c24a3c24e01b 100644
--- a/src/plugins/expressions/common/executor/executor.test.ts
+++ b/src/plugins/expressions/common/executor/executor.test.ts
@@ -52,12 +52,6 @@ describe('Executor', () => {
       executor.registerFunction(expressionFunctions.clog);
     });
 
-    test('can register all functions', () => {
-      const executor = new Executor();
-      for (const functionDefinition of expressionFunctions.functionSpecs)
-        executor.registerFunction(functionDefinition);
-    });
-
     test('can retrieve all functions', () => {
       const executor = new Executor();
       executor.registerFunction(expressionFunctions.clog);
@@ -67,12 +61,24 @@ describe('Executor', () => {
 
     test('can retrieve all functions - 2', () => {
       const executor = new Executor();
-      for (const functionDefinition of expressionFunctions.functionSpecs)
+      const functionSpecs = [
+        expressionFunctions.clog,
+        expressionFunctions.font,
+        expressionFunctions.variableSet,
+        expressionFunctions.variable,
+        expressionFunctions.theme,
+        expressionFunctions.cumulativeSum,
+        expressionFunctions.derivative,
+        expressionFunctions.movingAverage,
+        expressionFunctions.mapColumn,
+        expressionFunctions.math,
+      ];
+      for (const functionDefinition of functionSpecs) {
         executor.registerFunction(functionDefinition);
+      }
       const functions = executor.getFunctions();
-      expect(Object.keys(functions).sort()).toEqual(
-        expressionFunctions.functionSpecs.map((spec) => spec.name).sort()
-      );
+
+      expect(Object.keys(functions).sort()).toEqual(functionSpecs.map((spec) => spec.name).sort());
     });
   });
 
diff --git a/src/plugins/expressions/common/executor/executor.ts b/src/plugins/expressions/common/executor/executor.ts
index 1eea51a0e1ec4..a307172aff973 100644
--- a/src/plugins/expressions/common/executor/executor.ts
+++ b/src/plugins/expressions/common/executor/executor.ts
@@ -19,7 +19,6 @@ import { ExpressionType } from '../expression_types/expression_type';
 import { AnyExpressionTypeDefinition } from '../expression_types/types';
 import { ExpressionAstExpression, ExpressionAstFunction } from '../ast';
 import { ExpressionValueError, typeSpecs } from '../expression_types/specs';
-import { functionSpecs } from '../expression_functions/specs';
 import { getByAlias } from '../util';
 import { SavedObjectReference } from '../../../../core/types';
 import { PersistableStateService, SerializableState } from '../../../kibana_utils/common';
@@ -85,7 +84,7 @@ export class Executor<Context extends Record<string, unknown> = Record<string, u
   ): Executor<Ctx> {
     const executor = new Executor<Ctx>(state);
     for (const type of typeSpecs) executor.registerType(type);
-    for (const func of functionSpecs) executor.registerFunction(func);
+
     return executor;
   }
 
diff --git a/src/plugins/expressions/common/expression_functions/specs/index.ts b/src/plugins/expressions/common/expression_functions/specs/index.ts
index 9408b3a433712..20a6f9aac4567 100644
--- a/src/plugins/expressions/common/expression_functions/specs/index.ts
+++ b/src/plugins/expressions/common/expression_functions/specs/index.ts
@@ -6,31 +6,6 @@
  * Side Public License, v 1.
  */
 
-import { clog } from './clog';
-import { font } from './font';
-import { variableSet } from './var_set';
-import { variable } from './var';
-import { AnyExpressionFunctionDefinition } from '../types';
-import { theme } from './theme';
-import { cumulativeSum } from './cumulative_sum';
-import { derivative } from './derivative';
-import { movingAverage } from './moving_average';
-import { mapColumn } from './map_column';
-import { math } from './math';
-
-export const functionSpecs: AnyExpressionFunctionDefinition[] = [
-  clog,
-  font,
-  variableSet,
-  variable,
-  theme,
-  cumulativeSum,
-  derivative,
-  movingAverage,
-  mapColumn,
-  math,
-];
-
 export * from './clog';
 export * from './font';
 export * from './var_set';
@@ -39,5 +14,6 @@ export * from './theme';
 export * from './cumulative_sum';
 export * from './derivative';
 export * from './moving_average';
+export * from './ui_setting';
 export { mapColumn, MapColumnArguments } from './map_column';
 export { math, MathArguments, MathInput } from './math';
diff --git a/src/plugins/expressions/common/expression_functions/specs/map_column.ts b/src/plugins/expressions/common/expression_functions/specs/map_column.ts
index 7939441ff0d60..7ea96ee7fdde8 100644
--- a/src/plugins/expressions/common/expression_functions/specs/map_column.ts
+++ b/src/plugins/expressions/common/expression_functions/specs/map_column.ts
@@ -6,16 +6,16 @@
  * Side Public License, v 1.
  */
 
-import { Observable } from 'rxjs';
-import { take } from 'rxjs/operators';
+import { Observable, defer, of, zip } from 'rxjs';
+import { map } from 'rxjs/operators';
 import { i18n } from '@kbn/i18n';
 import { ExpressionFunctionDefinition } from '../types';
-import { Datatable, getType } from '../../expression_types';
+import { Datatable, DatatableColumn, getType } from '../../expression_types';
 
 export interface MapColumnArguments {
   id?: string | null;
   name: string;
-  expression?(datatable: Datatable): Observable<boolean | number | string | null>;
+  expression(datatable: Datatable): Observable<boolean | number | string | null>;
   copyMetaFrom?: string | null;
 }
 
@@ -23,7 +23,7 @@ export const mapColumn: ExpressionFunctionDefinition<
   'mapColumn',
   Datatable,
   MapColumnArguments,
-  Promise<Datatable>
+  Observable<Datatable>
 > = {
   name: 'mapColumn',
   aliases: ['mc'], // midnight commander. So many times I've launched midnight commander instead of moving a file.
@@ -80,57 +80,56 @@ export const mapColumn: ExpressionFunctionDefinition<
       default: null,
     },
   },
-  fn: (input, args) => {
-    const expression = (...params: Parameters<Required<MapColumnArguments>['expression']>) =>
-      args
-        .expression?.(...params)
-        .pipe(take(1))
-        .toPromise() ?? Promise.resolve(null);
+  fn(input, args) {
+    const existingColumnIndex = input.columns.findIndex(({ id, name }) =>
+      args.id ? id === args.id : name === args.name
+    );
+    const id = input.columns[existingColumnIndex]?.id ?? args.id ?? args.name;
 
-    const columns = [...input.columns];
-    const existingColumnIndex = columns.findIndex(({ id, name }) => {
-      if (args.id) {
-        return id === args.id;
-      }
-      return name === args.name;
-    });
-    const columnId =
-      existingColumnIndex === -1 ? args.id ?? args.name : columns[existingColumnIndex].id;
-
-    const rowPromises = input.rows.map((row) => {
-      return expression({
-        type: 'datatable',
-        columns,
-        rows: [row],
-      }).then((val) => ({
-        ...row,
-        [columnId]: val,
-      }));
-    });
+    return defer(() => {
+      const rows$ = input.rows.length
+        ? zip(
+            ...input.rows.map((row) =>
+              args
+                .expression({
+                  type: 'datatable',
+                  columns: [...input.columns],
+                  rows: [row],
+                })
+                .pipe(map((value) => ({ ...row, [id]: value })))
+            )
+          )
+        : of([]);
 
-    return Promise.all(rowPromises).then((rows) => {
-      const type = rows.length ? getType(rows[0][columnId]) : 'null';
-      const newColumn = {
-        id: columnId,
-        name: args.name,
-        meta: { type },
-      };
-      if (args.copyMetaFrom) {
-        const metaSourceFrom = columns.find(({ id }) => id === args.copyMetaFrom);
-        newColumn.meta = { ...newColumn.meta, ...(metaSourceFrom?.meta || {}) };
-      }
+      return rows$.pipe<Datatable>(
+        map((rows) => {
+          const type = getType(rows[0]?.[id]);
+          const newColumn: DatatableColumn = {
+            id,
+            name: args.name,
+            meta: { type, params: { id: type } },
+          };
+          if (args.copyMetaFrom) {
+            const metaSourceFrom = input.columns.find(
+              ({ id: columnId }) => columnId === args.copyMetaFrom
+            );
+            newColumn.meta = { ...newColumn.meta, ...(metaSourceFrom?.meta ?? {}) };
+          }
 
-      if (existingColumnIndex === -1) {
-        columns.push(newColumn);
-      } else {
-        columns[existingColumnIndex] = newColumn;
-      }
+          const columns = [...input.columns];
+          if (existingColumnIndex === -1) {
+            columns.push(newColumn);
+          } else {
+            columns[existingColumnIndex] = newColumn;
+          }
 
-      return {
-        type: 'datatable',
-        columns,
-        rows,
-      } as Datatable;
+          return {
+            columns,
+            rows,
+            type: 'datatable',
+          };
+        })
+      );
     });
   },
 };
diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/map_column.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/map_column.test.ts
index f5c1f3838f66c..bd934745fed72 100644
--- a/src/plugins/expressions/common/expression_functions/specs/tests/map_column.test.ts
+++ b/src/plugins/expressions/common/expression_functions/specs/tests/map_column.test.ts
@@ -6,7 +6,8 @@
  * Side Public License, v 1.
  */
 
-import { of } from 'rxjs';
+import { of, Observable } from 'rxjs';
+import { TestScheduler } from 'rxjs/testing';
 import { Datatable } from '../../../expression_types';
 import { mapColumn, MapColumnArguments } from '../map_column';
 import { emptyTable, functionWrapper, testTable } from './utils';
@@ -16,138 +17,227 @@ const pricePlusTwo = (datatable: Datatable) => of(datatable.rows[0].price + 2);
 describe('mapColumn', () => {
   const fn = functionWrapper(mapColumn);
   const runFn = (input: Datatable, args: MapColumnArguments) =>
-    fn(input, args) as Promise<Datatable>;
+    fn(input, args) as Observable<Datatable>;
+  let testScheduler: TestScheduler;
 
-  it('returns a datatable with a new column with the values from mapping a function over each row in a datatable', async () => {
-    const arbitraryRowIndex = 2;
-    const result = await runFn(testTable, {
-      id: 'pricePlusTwo',
-      name: 'pricePlusTwo',
-      expression: pricePlusTwo,
-    });
-
-    expect(result.type).toBe('datatable');
-    expect(result.columns).toEqual([
-      ...testTable.columns,
-      { id: 'pricePlusTwo', name: 'pricePlusTwo', meta: { type: 'number' } },
-    ]);
-    expect(result.columns[result.columns.length - 1]).toHaveProperty('name', 'pricePlusTwo');
-    expect(result.rows[arbitraryRowIndex]).toHaveProperty('pricePlusTwo');
+  beforeEach(() => {
+    testScheduler = new TestScheduler((actual, expected) => expect(actual).toStrictEqual(expected));
   });
 
-  it('allows the id arg to be optional, looking up by name instead', async () => {
-    const result = await runFn(testTable, { name: 'name label', expression: pricePlusTwo });
-    const nameColumnIndex = result.columns.findIndex(({ name }) => name === 'name label');
-    const arbitraryRowIndex = 4;
-
-    expect(result.type).toBe('datatable');
-    expect(result.columns).toHaveLength(testTable.columns.length);
-    expect(result.columns[nameColumnIndex]).toHaveProperty('id', 'name');
-    expect(result.columns[nameColumnIndex]).toHaveProperty('name', 'name label');
-    expect(result.columns[nameColumnIndex].meta).toHaveProperty('type', 'number');
-    expect(result.rows[arbitraryRowIndex]).toHaveProperty('name', 202);
-    expect(result.rows[arbitraryRowIndex]).not.toHaveProperty('name label');
+  it('returns a datatable with a new column with the values from mapping a function over each row in a datatable', () => {
+    testScheduler.run(({ expectObservable }) => {
+      expectObservable(
+        runFn(testTable, {
+          id: 'pricePlusTwo',
+          name: 'pricePlusTwo',
+          expression: pricePlusTwo,
+        })
+      ).toBe('(0|)', [
+        expect.objectContaining({
+          type: 'datatable',
+          columns: [
+            ...testTable.columns,
+            {
+              id: 'pricePlusTwo',
+              name: 'pricePlusTwo',
+              meta: { type: 'number', params: { id: 'number' } },
+            },
+          ],
+          rows: expect.arrayContaining([
+            expect.objectContaining({
+              pricePlusTwo: expect.anything(),
+            }),
+          ]),
+        }),
+      ]);
+    });
   });
 
-  it('allows a duplicate name when the ids are different', async () => {
-    const result = await runFn(testTable, {
-      id: 'new',
-      name: 'name label',
-      expression: pricePlusTwo,
+  it('allows the id arg to be optional, looking up by name instead', () => {
+    testScheduler.run(({ expectObservable }) => {
+      expectObservable(runFn(testTable, { name: 'name label', expression: pricePlusTwo })).toBe(
+        '(0|)',
+        [
+          expect.objectContaining({
+            type: 'datatable',
+            columns: expect.arrayContaining([
+              expect.objectContaining({
+                id: 'name',
+                name: 'name label',
+                meta: expect.objectContaining({ type: 'number' }),
+              }),
+            ]),
+            rows: expect.arrayContaining([
+              expect.objectContaining({
+                name: 202,
+              }),
+            ]),
+          }),
+        ]
+      );
     });
-    const nameColumnIndex = result.columns.findIndex(({ id }) => id === 'new');
-    const arbitraryRowIndex = 4;
-
-    expect(result.type).toBe('datatable');
-    expect(result.columns).toHaveLength(testTable.columns.length + 1);
-    expect(result.columns[nameColumnIndex]).toHaveProperty('id', 'new');
-    expect(result.columns[nameColumnIndex]).toHaveProperty('name', 'name label');
-    expect(result.columns[nameColumnIndex].meta).toHaveProperty('type', 'number');
-    expect(result.rows[arbitraryRowIndex]).toHaveProperty('new', 202);
   });
 
-  it('adds a column to empty tables', async () => {
-    const result = await runFn(emptyTable, { name: 'name', expression: pricePlusTwo });
+  it('allows a duplicate name when the ids are different', () => {
+    testScheduler.run(({ expectObservable }) => {
+      expectObservable(
+        runFn(testTable, {
+          id: 'new',
+          name: 'name label',
+          expression: pricePlusTwo,
+        })
+      ).toBe('(0|)', [
+        expect.objectContaining({
+          type: 'datatable',
+          columns: expect.arrayContaining([
+            expect.objectContaining({
+              id: 'new',
+              name: 'name label',
+              meta: expect.objectContaining({ type: 'number' }),
+            }),
+          ]),
+          rows: expect.arrayContaining([
+            expect.objectContaining({
+              new: 202,
+            }),
+          ]),
+        }),
+      ]);
+    });
+  });
 
-    expect(result.type).toBe('datatable');
-    expect(result.columns).toHaveLength(1);
-    expect(result.columns[0]).toHaveProperty('name', 'name');
-    expect(result.columns[0].meta).toHaveProperty('type', 'null');
+  it('overwrites existing column with the new column if an existing column name is provided', () => {
+    testScheduler.run(({ expectObservable }) => {
+      expectObservable(runFn(testTable, { name: 'name', expression: pricePlusTwo })).toBe('(0|)', [
+        expect.objectContaining({
+          type: 'datatable',
+          columns: expect.arrayContaining([
+            expect.objectContaining({
+              name: 'name',
+              meta: expect.objectContaining({ type: 'number' }),
+            }),
+          ]),
+          rows: expect.arrayContaining([
+            expect.objectContaining({
+              name: 202,
+            }),
+          ]),
+        }),
+      ]);
+    });
   });
 
-  it('should assign specific id, different from name, when id arg is passed for new columns', async () => {
-    const result = await runFn(emptyTable, { name: 'name', id: 'myid', expression: pricePlusTwo });
+  it('adds a column to empty tables', () => {
+    testScheduler.run(({ expectObservable }) => {
+      expectObservable(runFn(emptyTable, { name: 'name', expression: pricePlusTwo })).toBe('(0|)', [
+        expect.objectContaining({
+          type: 'datatable',
+          columns: [
+            expect.objectContaining({
+              name: 'name',
+              meta: expect.objectContaining({ type: 'null' }),
+            }),
+          ],
+        }),
+      ]);
+    });
+  });
 
-    expect(result.type).toBe('datatable');
-    expect(result.columns).toHaveLength(1);
-    expect(result.columns[0]).toHaveProperty('name', 'name');
-    expect(result.columns[0]).toHaveProperty('id', 'myid');
-    expect(result.columns[0].meta).toHaveProperty('type', 'null');
+  it('should assign specific id, different from name, when id arg is passed for copied column', () => {
+    testScheduler.run(({ expectObservable }) => {
+      expectObservable(
+        runFn(testTable, { name: 'name', id: 'myid', expression: pricePlusTwo })
+      ).toBe('(0|)', [
+        expect.objectContaining({
+          type: 'datatable',
+          columns: expect.arrayContaining([
+            expect.objectContaining({
+              id: 'myid',
+              name: 'name',
+              meta: expect.objectContaining({ type: 'number' }),
+            }),
+          ]),
+        }),
+      ]);
+    });
   });
 
-  it('should copy over the meta information from the specified column', async () => {
-    const result = await runFn(
-      {
-        ...testTable,
-        columns: [
-          ...testTable.columns,
-          // add a new entry
+  it('should copy over the meta information from the specified column', () => {
+    testScheduler.run(({ expectObservable }) => {
+      expectObservable(
+        runFn(
           {
-            id: 'myId',
-            name: 'myName',
-            meta: { type: 'date', params: { id: 'number', params: { digits: 2 } } },
+            ...testTable,
+            columns: [
+              ...testTable.columns,
+              // add a new entry
+              {
+                id: 'myId',
+                name: 'myName',
+                meta: { type: 'date', params: { id: 'number', params: { digits: 2 } } },
+              },
+            ],
+            rows: testTable.rows.map((row) => ({ ...row, myId: Date.now() })),
           },
-        ],
-        rows: testTable.rows.map((row) => ({ ...row, myId: Date.now() })),
-      },
-      { name: 'name', copyMetaFrom: 'myId', expression: pricePlusTwo }
-    );
-    const nameColumnIndex = result.columns.findIndex(({ name }) => name === 'name');
-
-    expect(result.type).toBe('datatable');
-    expect(result.columns[nameColumnIndex]).toEqual({
-      id: 'name',
-      name: 'name',
-      meta: { type: 'date', params: { id: 'number', params: { digits: 2 } } },
+          { name: 'name', copyMetaFrom: 'myId', expression: pricePlusTwo }
+        )
+      ).toBe('(0|)', [
+        expect.objectContaining({
+          type: 'datatable',
+          columns: expect.arrayContaining([
+            expect.objectContaining({
+              id: 'name',
+              name: 'name',
+              meta: { type: 'date', params: { id: 'number', params: { digits: 2 } } },
+            }),
+          ]),
+        }),
+      ]);
     });
   });
 
-  it('should be resilient if the references column for meta information does not exists', async () => {
-    const result = await runFn(emptyTable, {
-      name: 'name',
-      copyMetaFrom: 'time',
-      expression: pricePlusTwo,
+  it('should be resilient if the references column for meta information does not exists', () => {
+    testScheduler.run(({ expectObservable }) => {
+      expectObservable(
+        runFn(emptyTable, {
+          name: 'name',
+          copyMetaFrom: 'time',
+          expression: pricePlusTwo,
+        })
+      ).toBe('(0|)', [
+        expect.objectContaining({
+          type: 'datatable',
+          columns: [
+            expect.objectContaining({
+              id: 'name',
+              name: 'name',
+              meta: expect.objectContaining({ type: 'null' }),
+            }),
+          ],
+        }),
+      ]);
     });
-
-    expect(result.type).toBe('datatable');
-    expect(result.columns).toHaveLength(1);
-    expect(result.columns[0]).toHaveProperty('name', 'name');
-    expect(result.columns[0]).toHaveProperty('id', 'name');
-    expect(result.columns[0].meta).toHaveProperty('type', 'null');
   });
 
-  it('should correctly infer the type fromt he first row if the references column for meta information does not exists', async () => {
-    const result = await runFn(
-      { ...emptyTable, rows: [...emptyTable.rows, { value: 5 }] },
-      { name: 'value', copyMetaFrom: 'time', expression: pricePlusTwo }
-    );
-
-    expect(result.type).toBe('datatable');
-    expect(result.columns).toHaveLength(1);
-    expect(result.columns[0]).toHaveProperty('name', 'value');
-    expect(result.columns[0]).toHaveProperty('id', 'value');
-    expect(result.columns[0].meta).toHaveProperty('type', 'number');
-  });
-
-  describe('expression', () => {
-    it('maps null values to the new column', async () => {
-      const result = await runFn(testTable, { name: 'empty' });
-      const emptyColumnIndex = result.columns.findIndex(({ name }) => name === 'empty');
-      const arbitraryRowIndex = 8;
-
-      expect(result.columns[emptyColumnIndex]).toHaveProperty('name', 'empty');
-      expect(result.columns[emptyColumnIndex].meta).toHaveProperty('type', 'null');
-      expect(result.rows[arbitraryRowIndex]).toHaveProperty('empty', null);
+  it('should correctly infer the type fromt he first row if the references column for meta information does not exists', () => {
+    testScheduler.run(({ expectObservable }) => {
+      expectObservable(
+        runFn(
+          { ...emptyTable, rows: [...emptyTable.rows, { value: 5 }] },
+          { name: 'value', copyMetaFrom: 'time', expression: pricePlusTwo }
+        )
+      ).toBe('(0|)', [
+        expect.objectContaining({
+          type: 'datatable',
+          columns: [
+            expect.objectContaining({
+              id: 'value',
+              name: 'value',
+              meta: expect.objectContaining({ type: 'number' }),
+            }),
+          ],
+        }),
+      ]);
     });
   });
 });
diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/ui_setting.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/ui_setting.test.ts
new file mode 100644
index 0000000000000..fb2c87588a4d4
--- /dev/null
+++ b/src/plugins/expressions/common/expression_functions/specs/tests/ui_setting.test.ts
@@ -0,0 +1,78 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+jest.mock('../../../../common');
+
+import { IUiSettingsClient } from 'src/core/public';
+import { getUiSettingFn } from '../ui_setting';
+
+describe('uiSetting', () => {
+  describe('fn', () => {
+    let getStartDependencies: jest.MockedFunction<
+      Parameters<typeof getUiSettingFn>[0]['getStartDependencies']
+    >;
+    let uiSetting: ReturnType<typeof getUiSettingFn>;
+    let uiSettings: jest.Mocked<IUiSettingsClient>;
+
+    beforeEach(() => {
+      uiSettings = ({
+        get: jest.fn(),
+      } as unknown) as jest.Mocked<IUiSettingsClient>;
+      getStartDependencies = (jest.fn(async () => ({
+        uiSettings,
+      })) as unknown) as typeof getStartDependencies;
+
+      uiSetting = getUiSettingFn({ getStartDependencies });
+    });
+
+    it('should return a value', () => {
+      uiSettings.get.mockReturnValueOnce('value');
+
+      expect(uiSetting.fn(null, { parameter: 'something' }, {} as any)).resolves.toEqual({
+        type: 'ui_setting',
+        key: 'something',
+        value: 'value',
+      });
+    });
+
+    it('should pass a default value', async () => {
+      await uiSetting.fn(null, { parameter: 'something', default: 'default' }, {} as any);
+
+      expect(uiSettings.get).toHaveBeenCalledWith('something', 'default');
+    });
+
+    it('should throw an error when parameter does not exist', () => {
+      uiSettings.get.mockImplementationOnce(() => {
+        throw new Error();
+      });
+
+      expect(uiSetting.fn(null, { parameter: 'something' }, {} as any)).rejects.toEqual(
+        new Error('Invalid parameter "something".')
+      );
+    });
+
+    it('should get a request instance on the server-side', async () => {
+      const request = {};
+      await uiSetting.fn(null, { parameter: 'something' }, {
+        getKibanaRequest: () => request,
+      } as any);
+
+      const [[getKibanaRequest]] = getStartDependencies.mock.calls;
+
+      expect(getKibanaRequest()).toBe(request);
+    });
+
+    it('should throw an error if request is not provided on the server-side', async () => {
+      await uiSetting.fn(null, { parameter: 'something' }, {} as any);
+
+      const [[getKibanaRequest]] = getStartDependencies.mock.calls;
+
+      expect(getKibanaRequest).toThrow();
+    });
+  });
+});
diff --git a/src/plugins/expressions/common/expression_functions/specs/ui_setting.ts b/src/plugins/expressions/common/expression_functions/specs/ui_setting.ts
new file mode 100644
index 0000000000000..8e352e12d49c5
--- /dev/null
+++ b/src/plugins/expressions/common/expression_functions/specs/ui_setting.ts
@@ -0,0 +1,94 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import type { KibanaRequest } from 'src/core/server';
+import { i18n } from '@kbn/i18n';
+import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
+import { UiSetting } from '../../expression_types/specs/ui_setting';
+
+interface UiSettingsClient {
+  get<T>(key: string, defaultValue?: T): T | Promise<T>;
+}
+
+interface UiSettingStartDependencies {
+  uiSettings: UiSettingsClient;
+}
+
+interface UiSettingFnArguments {
+  getStartDependencies(getKibanaRequest: () => KibanaRequest): Promise<UiSettingStartDependencies>;
+}
+
+export interface UiSettingArguments {
+  default?: unknown;
+  parameter: string;
+}
+
+export type ExpressionFunctionUiSetting = ExpressionFunctionDefinition<
+  'uiSetting',
+  unknown,
+  UiSettingArguments,
+  Promise<UiSetting>
+>;
+
+export function getUiSettingFn({
+  getStartDependencies,
+}: UiSettingFnArguments): ExpressionFunctionUiSetting {
+  return {
+    name: 'uiSetting',
+    help: i18n.translate('expressions.functions.uiSetting.help', {
+      defaultMessage: 'Returns a UI settings parameter value.',
+    }),
+    args: {
+      default: {
+        help: i18n.translate('expressions.functions.uiSetting.args.default', {
+          defaultMessage: 'A default value in case of the parameter is not set.',
+        }),
+      },
+      parameter: {
+        aliases: ['_'],
+        help: i18n.translate('expressions.functions.uiSetting.args.parameter', {
+          defaultMessage: 'The parameter name.',
+        }),
+        required: true,
+        types: ['string'],
+      },
+    },
+    async fn(input, { default: defaultValue, parameter }, { getKibanaRequest }) {
+      const { uiSettings } = await getStartDependencies(() => {
+        const request = getKibanaRequest?.();
+        if (!request) {
+          throw new Error(
+            i18n.translate('expressions.functions.uiSetting.error.kibanaRequest', {
+              defaultMessage:
+                'A KibanaRequest is required to get UI settings on the server. ' +
+                'Please provide a request object to the expression execution params.',
+            })
+          );
+        }
+
+        return request;
+      });
+
+      try {
+        return {
+          type: 'ui_setting',
+          key: parameter,
+          value: await uiSettings.get(parameter, defaultValue),
+        };
+      } catch {
+        throw new Error(
+          i18n.translate('expressions.functions.uiSetting.error.parameter', {
+            defaultMessage: 'Invalid parameter "{parameter}".',
+            values: { parameter },
+          })
+        );
+      }
+    },
+  };
+}
diff --git a/src/plugins/expressions/common/expression_functions/types.ts b/src/plugins/expressions/common/expression_functions/types.ts
index b91e16d1804aa..e1378a27bdfc2 100644
--- a/src/plugins/expressions/common/expression_functions/types.ts
+++ b/src/plugins/expressions/common/expression_functions/types.ts
@@ -6,9 +6,8 @@
  * Side Public License, v 1.
  */
 
-import { UnwrapPromiseOrReturn } from '@kbn/utility-types';
 import { ArgumentType } from './arguments';
-import { TypeToString } from '../types/common';
+import { TypeToString, TypeString, UnmappedTypeStrings } from '../types/common';
 import { ExecutionContext } from '../execution/types';
 import {
   ExpressionFunctionClog,
@@ -47,7 +46,7 @@ export interface ExpressionFunctionDefinition<
   /**
    * Name of type of value this function outputs.
    */
-  type?: TypeToString<UnwrapPromiseOrReturn<Output>>;
+  type?: TypeString<Output> | UnmappedTypeStrings;
 
   /**
    * List of allowed type names for input value of this function. If this
diff --git a/src/plugins/expressions/common/expression_types/specs/index.ts b/src/plugins/expressions/common/expression_types/specs/index.ts
index 70427f8b337d8..c990d74672fcc 100644
--- a/src/plugins/expressions/common/expression_types/specs/index.ts
+++ b/src/plugins/expressions/common/expression_types/specs/index.ts
@@ -21,6 +21,7 @@ import { shape } from './shape';
 import { string } from './string';
 import { style } from './style';
 import { AnyExpressionTypeDefinition } from '../types';
+import { uiSetting } from './ui_setting';
 
 export const typeSpecs: AnyExpressionTypeDefinition[] = [
   boolean,
@@ -37,6 +38,7 @@ export const typeSpecs: AnyExpressionTypeDefinition[] = [
   shape,
   string,
   style,
+  uiSetting,
 ];
 
 export * from './boolean';
@@ -53,3 +55,4 @@ export * from './render';
 export * from './shape';
 export * from './string';
 export * from './style';
+export * from './ui_setting';
diff --git a/src/plugins/expressions/common/expression_types/specs/tests/ui_setting.test.ts b/src/plugins/expressions/common/expression_types/specs/tests/ui_setting.test.ts
new file mode 100644
index 0000000000000..a0a3d0d396b6e
--- /dev/null
+++ b/src/plugins/expressions/common/expression_types/specs/tests/ui_setting.test.ts
@@ -0,0 +1,79 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { UiSetting, uiSetting } from '../ui_setting';
+
+function createUiSetting(value: unknown, key = 'something'): UiSetting {
+  return {
+    key,
+    value,
+    type: 'ui_setting',
+  };
+}
+
+describe('uiSetting', () => {
+  describe('to', () => {
+    describe('render', () => {
+      it.each`
+        value          | expected
+        ${{ a: 'b' }}  | ${JSON.stringify({ a: 'b' })}
+        ${null}        | ${''}
+        ${'something'} | ${'something'}
+      `('should render "$value" as "$expected"', ({ expected, value }) => {
+        expect(uiSetting.to?.render(createUiSetting(value), {})).toHaveProperty(
+          'value.text',
+          expected
+        );
+      });
+    });
+
+    describe('datatable', () => {
+      it('should use parameter name as a datatable column', () => {
+        expect(uiSetting.to?.datatable(createUiSetting('value', 'column'), {})).toHaveProperty(
+          'columns.0',
+          expect.objectContaining({ id: 'column', name: 'column' })
+        );
+      });
+
+      it.each`
+        value          | type
+        ${null}        | ${'null'}
+        ${undefined}   | ${'null'}
+        ${'something'} | ${'string'}
+        ${['123']}     | ${'string'}
+        ${123}         | ${'number'}
+        ${[123]}       | ${'number'}
+        ${true}        | ${'boolean'}
+        ${{ a: 'b' }}  | ${'object'}
+        ${[]}          | ${'unknown'}
+      `('should determine $type type', ({ value, type }) => {
+        expect(uiSetting.to?.datatable(createUiSetting(value, 'column'), {})).toHaveProperty(
+          'columns.0.meta.type',
+          type
+        );
+      });
+
+      it('should put a value into a row', () => {
+        expect(uiSetting.to?.datatable(createUiSetting('value'), {})).toHaveProperty(
+          'rows.0.something',
+          'value'
+        );
+      });
+
+      it('should put an array value into multiple rows', () => {
+        expect(uiSetting.to?.datatable(createUiSetting(['a', 'b']), {})).toHaveProperty(
+          'rows',
+          expect.arrayContaining([
+            expect.objectContaining({ something: 'a' }),
+            expect.objectContaining({ something: 'b' }),
+          ])
+        );
+      });
+    });
+  });
+});
diff --git a/src/plugins/expressions/common/expression_types/specs/ui_setting.ts b/src/plugins/expressions/common/expression_types/specs/ui_setting.ts
new file mode 100644
index 0000000000000..aaea92e89a832
--- /dev/null
+++ b/src/plugins/expressions/common/expression_types/specs/ui_setting.ts
@@ -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
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { Datatable, DatatableColumnType } from './datatable';
+import { ExpressionTypeDefinition, ExpressionValueBoxed } from '../types';
+import { ExpressionValueRender } from './render';
+
+const name = 'ui_setting';
+
+function getType(value: unknown): DatatableColumnType {
+  if (value == null) {
+    return 'null';
+  }
+
+  if (Array.isArray(value)) {
+    return value.length ? getType(value[0]) : 'unknown';
+  }
+
+  if (['boolean', 'number', 'object', 'string'].includes(typeof value)) {
+    return typeof value as DatatableColumnType;
+  }
+
+  return 'unknown';
+}
+
+export type UiSetting = ExpressionValueBoxed<'ui_setting', { key: string; value: unknown }>;
+
+export const uiSetting: ExpressionTypeDefinition<'ui_setting', UiSetting> = {
+  name,
+  to: {
+    boolean({ value }) {
+      return Boolean(value);
+    },
+    number({ value }) {
+      return Number(value);
+    },
+    string({ value }) {
+      return String(value ?? '');
+    },
+    render({ value }): ExpressionValueRender<{ text: string }> {
+      return {
+        type: 'render',
+        as: 'text',
+        value: {
+          text:
+            typeof value === 'object' && value !== null
+              ? JSON.stringify(value)
+              : String(value ?? ''),
+        },
+      };
+    },
+    datatable({ key, value }): Datatable {
+      return {
+        type: 'datatable',
+        columns: [{ id: key, name: key, meta: { type: getType(value) } }],
+        rows: (Array.isArray(value) ? value : [value]).map((cell) => ({ [key]: cell })),
+      };
+    },
+  },
+};
diff --git a/src/plugins/expressions/common/service/expressions_services.ts b/src/plugins/expressions/common/service/expressions_services.ts
index d57c1748954ab..a8839c9b0d71e 100644
--- a/src/plugins/expressions/common/service/expressions_services.ts
+++ b/src/plugins/expressions/common/service/expressions_services.ts
@@ -19,6 +19,18 @@ import { AnyExpressionFunctionDefinition } from '../expression_functions';
 import { SavedObjectReference } from '../../../../core/types';
 import { PersistableStateService, SerializableState } from '../../../kibana_utils/common';
 import { Adapters } from '../../../inspector/common/adapters';
+import {
+  clog,
+  font,
+  variableSet,
+  variable,
+  theme,
+  cumulativeSum,
+  derivative,
+  movingAverage,
+  mapColumn,
+  math,
+} from '../expression_functions';
 
 /**
  * The public contract that `ExpressionsService` provides to other plugins
@@ -269,7 +281,7 @@ export class ExpressionsService implements PersistableStateService<ExpressionAst
   public readonly fork = () => {
     const executor = this.executor.fork();
     const renderers = this.renderers;
-    const fork = new ExpressionsService({ executor, renderers });
+    const fork = new (this.constructor as typeof ExpressionsService)({ executor, renderers });
 
     return fork;
   };
@@ -318,7 +330,22 @@ export class ExpressionsService implements PersistableStateService<ExpressionAst
    * Returns Kibana Platform *setup* life-cycle contract. Useful to return the
    * same contract on server-side and browser-side.
    */
-  public setup(): ExpressionsServiceSetup {
+  public setup(...args: unknown[]): ExpressionsServiceSetup {
+    for (const fn of [
+      clog,
+      font,
+      variableSet,
+      variable,
+      theme,
+      cumulativeSum,
+      derivative,
+      movingAverage,
+      mapColumn,
+      math,
+    ]) {
+      this.registerFunction(fn);
+    }
+
     return this;
   }
 
@@ -326,7 +353,7 @@ export class ExpressionsService implements PersistableStateService<ExpressionAst
    * Returns Kibana Platform *start* life-cycle contract. Useful to return the
    * same contract on server-side and browser-side.
    */
-  public start(): ExpressionsServiceStart {
+  public start(...args: unknown[]): ExpressionsServiceStart {
     return this;
   }
 
diff --git a/src/plugins/expressions/common/test_helpers/expression_functions/index.ts b/src/plugins/expressions/common/test_helpers/expression_functions/index.ts
index b73d1e0208f89..cb49cfa359205 100644
--- a/src/plugins/expressions/common/test_helpers/expression_functions/index.ts
+++ b/src/plugins/expressions/common/test_helpers/expression_functions/index.ts
@@ -13,7 +13,19 @@ import { introspectContext } from './introspect_context';
 import { mult } from './mult';
 import { sleep } from './sleep';
 import { sum } from './sum';
-import { AnyExpressionFunctionDefinition } from '../../expression_functions';
+import {
+  AnyExpressionFunctionDefinition,
+  clog,
+  font,
+  variableSet,
+  variable,
+  theme,
+  cumulativeSum,
+  derivative,
+  movingAverage,
+  mapColumn,
+  math,
+} from '../../expression_functions';
 
 export const functionTestSpecs: AnyExpressionFunctionDefinition[] = [
   access,
@@ -23,4 +35,14 @@ export const functionTestSpecs: AnyExpressionFunctionDefinition[] = [
   mult,
   sleep,
   sum,
+  clog,
+  font,
+  variableSet,
+  variable,
+  theme,
+  cumulativeSum,
+  derivative,
+  movingAverage,
+  mapColumn,
+  math,
 ];
diff --git a/src/plugins/expressions/public/expression_functions/index.ts b/src/plugins/expressions/public/expression_functions/index.ts
new file mode 100644
index 0000000000000..eb36291c613c6
--- /dev/null
+++ b/src/plugins/expressions/public/expression_functions/index.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
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+export * from './ui_setting';
diff --git a/src/plugins/expressions/public/expression_functions/ui_setting.ts b/src/plugins/expressions/public/expression_functions/ui_setting.ts
new file mode 100644
index 0000000000000..dd5be4ad736b2
--- /dev/null
+++ b/src/plugins/expressions/public/expression_functions/ui_setting.ts
@@ -0,0 +1,20 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { CoreSetup } from 'src/core/public';
+import { getUiSettingFn as getCommonUiSettingFn } from '../../common';
+
+export function getUiSettingFn({ getStartServices }: Pick<CoreSetup, 'getStartServices'>) {
+  return getCommonUiSettingFn({
+    async getStartDependencies() {
+      const [{ uiSettings }] = await getStartServices();
+
+      return { uiSettings };
+    },
+  });
+}
diff --git a/src/plugins/expressions/public/plugin.test.ts b/src/plugins/expressions/public/plugin.test.ts
index b83c92f5d1a96..93353ebbb51b6 100644
--- a/src/plugins/expressions/public/plugin.test.ts
+++ b/src/plugins/expressions/public/plugin.test.ts
@@ -8,7 +8,7 @@
 
 import { expressionsPluginMock } from './mocks';
 import { add } from '../common/test_helpers/expression_functions/add';
-import { ExpressionsService } from '../common';
+import { ExpressionsService } from './services';
 
 describe('ExpressionsPublicPlugin', () => {
   test('can instantiate from mocks', async () => {
diff --git a/src/plugins/expressions/public/plugin.ts b/src/plugins/expressions/public/plugin.ts
index 2410ad8741312..37d519ac45133 100644
--- a/src/plugins/expressions/public/plugin.ts
+++ b/src/plugins/expressions/public/plugin.ts
@@ -6,9 +6,15 @@
  * Side Public License, v 1.
  */
 
+import { pick } from 'lodash';
 import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public';
-import { ExpressionsService, ExpressionsServiceSetup, ExpressionsServiceStart } from '../common';
-import { setRenderersRegistry, setNotifications, setExpressionsService } from './services';
+import { ExpressionsServiceSetup, ExpressionsServiceStart } from '../common';
+import {
+  ExpressionsService,
+  setRenderersRegistry,
+  setNotifications,
+  setExpressionsService,
+} from './services';
 import { ReactExpressionRenderer } from './react_expression_renderer';
 import { ExpressionLoader, IExpressionLoader, loader } from './loader';
 import { render, ExpressionRenderHandler } from './render';
@@ -51,7 +57,7 @@ export class ExpressionsPublicPlugin implements Plugin<ExpressionsSetup, Express
     setRenderersRegistry(renderers);
     setExpressionsService(expressions);
 
-    const setup = expressions.setup();
+    const setup = expressions.setup(pick(core, 'getStartServices'));
 
     return Object.freeze(setup);
   }
diff --git a/src/plugins/expressions/public/public.api.md b/src/plugins/expressions/public/public.api.md
index 9c17a2753cfc9..ea11f7e728e45 100644
--- a/src/plugins/expressions/public/public.api.md
+++ b/src/plugins/expressions/public/public.api.md
@@ -375,7 +375,7 @@ export interface ExpressionFunctionDefinition<Name extends string, Input, Argume
     help: string;
     inputTypes?: Array<TypeToString<Input>>;
     name: Name;
-    type?: TypeToString<UnwrapPromiseOrReturn<Output>>;
+    type?: TypeString<Output> | UnmappedTypeStrings;
 }
 
 // @public
@@ -612,8 +612,8 @@ export class ExpressionsService implements PersistableStateService<ExpressionAst
     readonly renderers: ExpressionRendererRegistry;
     // (undocumented)
     readonly run: ExpressionsServiceStart['run'];
-    setup(): ExpressionsServiceSetup;
-    start(): ExpressionsServiceStart;
+    setup(...args: unknown[]): ExpressionsServiceSetup;
+    start(...args: unknown[]): ExpressionsServiceStart;
     // (undocumented)
     stop(): void;
     readonly telemetry: (state: ExpressionAstExpression, telemetryData?: Record<string, any>) => Record<string, any>;
diff --git a/src/plugins/expressions/public/services/expressions_services.ts b/src/plugins/expressions/public/services/expressions_services.ts
new file mode 100644
index 0000000000000..388af81629c31
--- /dev/null
+++ b/src/plugins/expressions/public/services/expressions_services.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
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { CoreSetup } from 'src/core/public';
+import { ExpressionsService as CommonExpressionsService } from '../../common';
+import { getUiSettingFn } from '../expression_functions';
+
+export class ExpressionsService extends CommonExpressionsService {
+  setup({ getStartServices }: Pick<CoreSetup, 'getStartServices'>) {
+    this.registerFunction(getUiSettingFn({ getStartServices }));
+
+    return super.setup();
+  }
+}
diff --git a/src/plugins/expressions/public/services.ts b/src/plugins/expressions/public/services/index.ts
similarity index 87%
rename from src/plugins/expressions/public/services.ts
rename to src/plugins/expressions/public/services/index.ts
index a700e54d77e19..db473037a0a4a 100644
--- a/src/plugins/expressions/public/services.ts
+++ b/src/plugins/expressions/public/services/index.ts
@@ -7,8 +7,8 @@
  */
 
 import { NotificationsStart } from 'kibana/public';
-import { createGetterSetter } from '../../kibana_utils/public';
-import { ExpressionsService, ExpressionRendererRegistry } from '../common';
+import { createGetterSetter } from '../../../kibana_utils/public';
+import { ExpressionsService, ExpressionRendererRegistry } from '../../common';
 
 export const [getNotifications, setNotifications] = createGetterSetter<NotificationsStart>(
   'Notifications'
@@ -23,3 +23,5 @@ export const [
   getExpressionsService,
   setExpressionsService,
 ] = createGetterSetter<ExpressionsService>('ExpressionsService');
+
+export * from './expressions_services';
diff --git a/src/plugins/expressions/server/expression_functions/index.ts b/src/plugins/expressions/server/expression_functions/index.ts
new file mode 100644
index 0000000000000..eb36291c613c6
--- /dev/null
+++ b/src/plugins/expressions/server/expression_functions/index.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
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+export * from './ui_setting';
diff --git a/src/plugins/expressions/server/expression_functions/ui_setting.ts b/src/plugins/expressions/server/expression_functions/ui_setting.ts
new file mode 100644
index 0000000000000..0d3d5b1c1f997
--- /dev/null
+++ b/src/plugins/expressions/server/expression_functions/ui_setting.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
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { CoreSetup } from 'src/core/server';
+import { getUiSettingFn as getCommonUiSettingFn } from '../../common';
+
+export function getUiSettingFn({ getStartServices }: Pick<CoreSetup, 'getStartServices'>) {
+  return getCommonUiSettingFn({
+    async getStartDependencies(getKibanaRequest) {
+      const [{ savedObjects, uiSettings }] = await getStartServices();
+      const savedObjectsClient = savedObjects.getScopedClient(getKibanaRequest());
+      const uiSettingsClient = uiSettings.asScopedToClient(savedObjectsClient);
+
+      return { uiSettings: uiSettingsClient };
+    },
+  });
+}
diff --git a/src/plugins/expressions/server/plugin.ts b/src/plugins/expressions/server/plugin.ts
index 2c638d496ece6..2e45daf6e0f8c 100644
--- a/src/plugins/expressions/server/plugin.ts
+++ b/src/plugins/expressions/server/plugin.ts
@@ -6,6 +6,7 @@
  * Side Public License, v 1.
  */
 
+import { pick } from 'lodash';
 import { CoreStart, CoreSetup, Plugin, PluginInitializerContext } from 'src/core/server';
 import { ExpressionsService, ExpressionsServiceSetup, ExpressionsServiceStart } from '../common';
 
@@ -24,7 +25,7 @@ export class ExpressionsServerPlugin
       environment: 'server',
     });
 
-    const setup = this.expressions.setup();
+    const setup = this.expressions.setup(pick(core, 'getStartServices'));
 
     return Object.freeze(setup);
   }
diff --git a/src/plugins/expressions/server/server.api.md b/src/plugins/expressions/server/server.api.md
index 12af0480fac93..bc0980121b827 100644
--- a/src/plugins/expressions/server/server.api.md
+++ b/src/plugins/expressions/server/server.api.md
@@ -347,7 +347,7 @@ export interface ExpressionFunctionDefinition<Name extends string, Input, Argume
     help: string;
     inputTypes?: Array<TypeToString<Input>>;
     name: Name;
-    type?: TypeToString<UnwrapPromiseOrReturn<Output>>;
+    type?: TypeString<Output> | UnmappedTypeStrings;
 }
 
 // @public
diff --git a/src/plugins/expressions/server/services/expressions_services.ts b/src/plugins/expressions/server/services/expressions_services.ts
new file mode 100644
index 0000000000000..914745436f151
--- /dev/null
+++ b/src/plugins/expressions/server/services/expressions_services.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
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { CoreSetup } from 'src/core/server';
+import { ExpressionsService as CommonExpressionsService } from '../../common';
+import { getUiSettingFn } from '../expression_functions';
+
+export class ExpressionsService extends CommonExpressionsService {
+  setup({ getStartServices }: Pick<CoreSetup, 'getStartServices'>) {
+    this.registerFunction(getUiSettingFn({ getStartServices }));
+
+    return super.setup();
+  }
+}
diff --git a/src/plugins/expressions/server/services/index.ts b/src/plugins/expressions/server/services/index.ts
new file mode 100644
index 0000000000000..c239c4efdb02c
--- /dev/null
+++ b/src/plugins/expressions/server/services/index.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
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+export * from './expressions_services';
diff --git a/src/plugins/kibana_react/public/code_editor/__snapshots__/code_editor.test.tsx.snap b/src/plugins/kibana_react/public/code_editor/__snapshots__/code_editor.test.tsx.snap
index a779ef540d72e..d4fb5a708e440 100644
--- a/src/plugins/kibana_react/public/code_editor/__snapshots__/code_editor.test.tsx.snap
+++ b/src/plugins/kibana_react/public/code_editor/__snapshots__/code_editor.test.tsx.snap
@@ -11,6 +11,7 @@ exports[`is rendered 1`] = `
     onChange={[Function]}
     options={
       Object {
+        "matchBrackets": "never",
         "minimap": Object {
           "enabled": false,
         },
@@ -39,6 +40,7 @@ exports[`is rendered 1`] = `
     nodeType="div"
     onResize={[Function]}
     querySelector={null}
+    refreshMode="debounce"
     refreshRate={1000}
     skipOnMount={false}
     targetDomEl={null}
diff --git a/src/plugins/kibana_react/public/code_editor/code_editor.tsx b/src/plugins/kibana_react/public/code_editor/code_editor.tsx
index 55e10e7861e51..251f05950da22 100644
--- a/src/plugins/kibana_react/public/code_editor/code_editor.tsx
+++ b/src/plugins/kibana_react/public/code_editor/code_editor.tsx
@@ -187,10 +187,16 @@ export class CodeEditor extends React.Component<Props, {}> {
             wordBasedSuggestions: false,
             wordWrap: 'on',
             wrappingIndent: 'indent',
+            matchBrackets: 'never',
             ...options,
           }}
         />
-        <ReactResizeDetector handleWidth handleHeight onResize={this._updateDimensions} />
+        <ReactResizeDetector
+          handleWidth
+          handleHeight
+          onResize={this._updateDimensions}
+          refreshMode="debounce"
+        />
       </>
     );
   }
diff --git a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts
index 1fa7d8e846c9d..e7c6b53ff97b3 100644
--- a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts
+++ b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts
@@ -148,6 +148,7 @@ export const applicationUsageSchema = {
   maps: commonSchema,
   ml: commonSchema,
   monitoring: commonSchema,
+  observabilityCases: commonSchema,
   'observability-overview': commonSchema,
   osquery: commonSchema,
   security_account: commonSchema,
diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json
index 7b6c4ba9788f1..51df1d3162b7c 100644
--- a/src/plugins/telemetry/schema/oss_plugins.json
+++ b/src/plugins/telemetry/schema/oss_plugins.json
@@ -3970,6 +3970,137 @@
             }
           }
         },
+        "observabilityCases": {
+          "properties": {
+            "appId": {
+              "type": "keyword",
+              "_meta": {
+                "description": "The application being tracked"
+              }
+            },
+            "viewId": {
+              "type": "keyword",
+              "_meta": {
+                "description": "Always `main`"
+              }
+            },
+            "clicks_total": {
+              "type": "long",
+              "_meta": {
+                "description": "General number of clicks in the application since we started counting them"
+              }
+            },
+            "clicks_7_days": {
+              "type": "long",
+              "_meta": {
+                "description": "General number of clicks in the application over the last 7 days"
+              }
+            },
+            "clicks_30_days": {
+              "type": "long",
+              "_meta": {
+                "description": "General number of clicks in the application over the last 30 days"
+              }
+            },
+            "clicks_90_days": {
+              "type": "long",
+              "_meta": {
+                "description": "General number of clicks in the application over the last 90 days"
+              }
+            },
+            "minutes_on_screen_total": {
+              "type": "float",
+              "_meta": {
+                "description": "Minutes the application is active and on-screen since we started counting them."
+              }
+            },
+            "minutes_on_screen_7_days": {
+              "type": "float",
+              "_meta": {
+                "description": "Minutes the application is active and on-screen over the last 7 days"
+              }
+            },
+            "minutes_on_screen_30_days": {
+              "type": "float",
+              "_meta": {
+                "description": "Minutes the application is active and on-screen over the last 30 days"
+              }
+            },
+            "minutes_on_screen_90_days": {
+              "type": "float",
+              "_meta": {
+                "description": "Minutes the application is active and on-screen over the last 90 days"
+              }
+            },
+            "views": {
+              "type": "array",
+              "items": {
+                "properties": {
+                  "appId": {
+                    "type": "keyword",
+                    "_meta": {
+                      "description": "The application being tracked"
+                    }
+                  },
+                  "viewId": {
+                    "type": "keyword",
+                    "_meta": {
+                      "description": "The application view being tracked"
+                    }
+                  },
+                  "clicks_total": {
+                    "type": "long",
+                    "_meta": {
+                      "description": "General number of clicks in the application sub view since we started counting them"
+                    }
+                  },
+                  "clicks_7_days": {
+                    "type": "long",
+                    "_meta": {
+                      "description": "General number of clicks in the active application sub view over the last 7 days"
+                    }
+                  },
+                  "clicks_30_days": {
+                    "type": "long",
+                    "_meta": {
+                      "description": "General number of clicks in the active application sub view over the last 30 days"
+                    }
+                  },
+                  "clicks_90_days": {
+                    "type": "long",
+                    "_meta": {
+                      "description": "General number of clicks in the active application sub view over the last 90 days"
+                    }
+                  },
+                  "minutes_on_screen_total": {
+                    "type": "float",
+                    "_meta": {
+                      "description": "Minutes the application sub view is active and on-screen since we started counting them."
+                    }
+                  },
+                  "minutes_on_screen_7_days": {
+                    "type": "float",
+                    "_meta": {
+                      "description": "Minutes the application is active and on-screen active application sub view over the last 7 days"
+                    }
+                  },
+                  "minutes_on_screen_30_days": {
+                    "type": "float",
+                    "_meta": {
+                      "description": "Minutes the application is active and on-screen active application sub view over the last 30 days"
+                    }
+                  },
+                  "minutes_on_screen_90_days": {
+                    "type": "float",
+                    "_meta": {
+                      "description": "Minutes the application is active and on-screen active application sub view over the last 90 days"
+                    }
+                  }
+                }
+              }
+            }
+          }
+        },
         "observability-overview": {
           "properties": {
             "appId": {
diff --git a/src/plugins/vis_type_tagcloud/public/components/tag_cloud.test.js b/src/plugins/vis_type_tagcloud/public/components/tag_cloud.test.js
index 2fb2be0ace7cd..eb575457146c5 100644
--- a/src/plugins/vis_type_tagcloud/public/components/tag_cloud.test.js
+++ b/src/plugins/vis_type_tagcloud/public/components/tag_cloud.test.js
@@ -150,7 +150,8 @@ describe('tag cloud tests', () => {
   });
 
   [5, 100, 200, 300, 500].forEach((timeout) => {
-    describe(`should only send single renderComplete event at the very end, using ${timeout}ms timeout`, () => {
+    // FLAKY: https://github.com/elastic/kibana/issues/94043
+    describe.skip(`should only send single renderComplete event at the very end, using ${timeout}ms timeout`, () => {
       beforeEach(async () => {
         //TagCloud takes at least 600ms to complete (due to d3 animation)
         //renderComplete should only notify at the last one
diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/data.json b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/data.json
new file mode 100644
index 0000000000000..349545be44316
--- /dev/null
+++ b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/data.json
@@ -0,0 +1,239 @@
+{
+  "type": "doc",
+  "value": {
+    "id": "index-pattern:8963ca30-3224-11e8-a572-ffca06da1357",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "index-pattern": {
+        "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]",
+        "title": "saved_objects*"
+      },
+      "migrationVersion": {
+        "index-pattern": "7.11.0"
+      },
+      "references": [
+      ],
+      "type": "index-pattern",
+      "updated_at": "2018-03-28T01:08:34.290Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "config:7.0.0-alpha1",
+    "index": ".kibana",
+    "source": {
+      "config": {
+        "buildNum": 8467,
+        "defaultIndex": "8963ca30-3224-11e8-a572-ffca06da1357",
+        "telemetry:optIn": false
+      },
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "config": "7.13.0"
+      },
+      "references": [
+      ],
+      "type": "config",
+      "updated_at": "2018-03-28T01:08:39.248Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "search:960372e0-3224-11e8-a572-ffca06da1357",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "search": "7.9.3"
+      },
+      "references": [
+        {
+          "id": "8963ca30-3224-11e8-a572-ffca06da1357",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "search": {
+        "columns": [
+          "_source"
+        ],
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"id:3\",\"language\":\"lucene\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "sort": [
+          [
+            "_score",
+            "desc"
+          ]
+        ],
+        "title": "OneRecord",
+        "version": 1
+      },
+      "type": "search",
+      "updated_at": "2018-03-28T01:08:55.182Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:a42c0580-3224-11e8-a572-ffca06da1357",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "960372e0-3224-11e8-a572-ffca06da1357",
+          "name": "search_0",
+          "type": "search"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-03-28T01:09:18.936Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}"
+        },
+        "savedSearchRefName": "search_0",
+        "title": "VisualizationFromSavedSearch",
+        "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}",
+        "version": 1,
+        "visState": "{\"title\":\"VisualizationFromSavedSearch\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\",\"showToolbar\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:add810b0-3224-11e8-a572-ffca06da1357",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "8963ca30-3224-11e8-a572-ffca06da1357",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-03-28T01:09:35.163Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Amazing Visualization",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Visualization\",\"type\":\"metric\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"type\":\"metric\",\"metric\":{\"percentageMode\":false,\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"metricColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"labels\":{\"show\":true},\"invertColors\":false,\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:b70c7ae0-3224-11e8-a572-ffca06da1357",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[{\"version\":\"7.0.0-alpha1\",\"gridData\":{\"w\":24,\"h\":15,\"x\":0,\"y\":0,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_0\"},{\"version\":\"7.0.0-alpha1\",\"gridData\":{\"w\":24,\"h\":15,\"x\":24,\"y\":0,\"i\":\"2\"},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"}]",
+        "timeRestore": false,
+        "title": "Dashboard",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "add810b0-3224-11e8-a572-ffca06da1357",
+          "name": "panel_0",
+          "type": "visualization"
+        },
+        {
+          "id": "a42c0580-3224-11e8-a572-ffca06da1357",
+          "name": "panel_1",
+          "type": "visualization"
+        }
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-03-28T01:09:50.606Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:d70c7ae0-3224-11e8-a572-ffca82da1357",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[{\"version\":\"7.0.0-alpha1\",\"gridData\":{\"w\":24,\"h\":15,\"x\":0,\"y\":0,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_0\"},{\"version\":\"7.0.0-alpha1\",\"gridData\":{\"w\":24,\"h\":15,\"x\":24,\"y\":0,\"i\":\"2\"},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"}]",
+        "timeRestore": false,
+        "title": "Amazing Dashboard",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "add810b0-3224-11e8-a572-ffca06da1357",
+          "name": "panel_0",
+          "type": "visualization"
+        },
+        {
+          "id": "a42c0580-3224-11e8-a572-ffca06da1357",
+          "name": "panel_1",
+          "type": "visualization"
+        }
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-03-28T01:09:50.606Z"
+    },
+    "type": "_doc"
+  }
+}
\ No newline at end of file
diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/data.json.gz b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/data.json.gz
deleted file mode 100644
index 1c327e7e0769b..0000000000000
Binary files a/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/data.json.gz and /dev/null differ
diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json
index d2177481130a2..f44bb7463e9eb 100644
--- a/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json
+++ b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json
@@ -2,140 +2,331 @@
   "type": "index",
   "value": {
     "aliases": {
+      ".kibana_$KIBANA_PACKAGE_VERSION": {},
       ".kibana": {}
     },
-    "index": ".kibana_1",
-    "settings": {
-      "index": {
-        "number_of_shards": "1",
-        "auto_expand_replicas": "0-1",
-        "number_of_replicas": "0"
-      }
-    },
+    "index": ".kibana_$KIBANA_PACKAGE_VERSION_001",
     "mappings": {
+      "_meta": {
+        "migrationMappingPropertyHashes": {
+          "application_usage_daily": "43b8830d5d0df85a6823d290885fc9fd",
+          "application_usage_totals": "3d1b76c39bfb2cc8296b024d73854724",
+          "application_usage_transactional": "3d1b76c39bfb2cc8296b024d73854724",
+          "config": "c63748b75f39d0c54de12d12c1ccbc20",
+          "core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724",
+          "coreMigrationVersion": "2f4316de49999235636386fe51dc06c1",
+          "dashboard": "40554caf09725935e2c02e02563a2d07",
+          "index-pattern": "45915a1ad866812242df474eb0479052",
+          "kql-telemetry": "d12a98a6f19a2d273696597547e064ee",
+          "legacy-url-alias": "6155300fd11a00e23d5cbaa39f0fce0a",
+          "migrationVersion": "4a1746014a75ade3a714e1db5763276f",
+          "namespace": "2f4316de49999235636386fe51dc06c1",
+          "namespaces": "2f4316de49999235636386fe51dc06c1",
+          "originId": "2f4316de49999235636386fe51dc06c1",
+          "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9",
+          "references": "7997cf5a56cc02bdc9c93361bde732b0",
+          "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4",
+          "search": "db2c00e39b36f40930a3b9fc71c823e1",
+          "search-telemetry": "3d1b76c39bfb2cc8296b024d73854724",
+          "telemetry": "36a616f7026dfa617d6655df850fe16d",
+          "timelion-sheet": "9a2a2748877c7a7b582fef201ab1d4cf",
+          "type": "2f4316de49999235636386fe51dc06c1",
+          "ui-counter": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "updated_at": "00da57df13e94e9d98437d13ace4bfe0",
+          "url": "c7f66a0df8b1b52f17c28c4adb111105",
+          "usage-counters": "8cc260bdceffec4ffc3ad165c97dc1b4",
+          "visualization": "f819cf6636b75c9e76ba733a0c6ef355"
+        }
+      },
       "dynamic": "strict",
       "properties": {
+        "application_usage_daily": {
+          "dynamic": "false",
+          "properties": {
+            "timestamp": {
+              "type": "date"
+            }
+          }
+        },
+        "application_usage_totals": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "application_usage_transactional": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "config": {
-          "dynamic": "true",
+          "dynamic": "false",
           "properties": {
             "buildNum": {
               "type": "keyword"
-            },
-            "defaultIndex": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 256
-                }
-              }
-            },
-            "telemetry:optIn": {
-              "type": "boolean"
             }
           }
         },
+        "core-usage-stats": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "coreMigrationVersion": {
+          "type": "keyword"
+        },
         "dashboard": {
           "properties": {
             "description": {
               "type": "text"
             },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "optionsJSON": {
+              "index": false,
               "type": "text"
             },
             "panelsJSON": {
+              "index": false,
               "type": "text"
             },
             "refreshInterval": {
               "properties": {
                 "display": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "keyword"
                 },
                 "pause": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "boolean"
                 },
                 "section": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 },
                 "value": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 }
               }
             },
             "timeFrom": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "timeRestore": {
+              "doc_values": false,
+              "index": false,
               "type": "boolean"
             },
             "timeTo": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
-            "uiStateJSON": {
-              "type": "text"
-            },
             "version": {
               "type": "integer"
             }
           }
         },
         "index-pattern": {
+          "dynamic": "false",
           "properties": {
-            "fieldFormatMap": {
-              "type": "text"
-            },
-            "fields": {
+            "title": {
               "type": "text"
             },
-            "intervalName": {
+            "type": {
               "type": "keyword"
+            }
+          }
+        },
+        "kql-telemetry": {
+          "properties": {
+            "optInCount": {
+              "type": "long"
             },
-            "notExpandable": {
+            "optOutCount": {
+              "type": "long"
+            }
+          }
+        },
+        "legacy-url-alias": {
+          "dynamic": "false",
+          "properties": {
+            "disabled": {
               "type": "boolean"
             },
-            "sourceFilters": {
-              "type": "text"
+            "sourceId": {
+              "type": "keyword"
             },
-            "timeFieldName": {
+            "targetType": {
               "type": "keyword"
+            }
+          }
+        },
+        "migrationVersion": {
+          "dynamic": "true",
+          "properties": {
+            "config": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            },
+            "dashboard": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            },
+            "index-pattern": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            },
+            "search": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            },
+            "visualization": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            }
+          }
+        },
+        "namespace": {
+          "type": "keyword"
+        },
+        "namespaces": {
+          "type": "keyword"
+        },
+        "originId": {
+          "type": "keyword"
+        },
+        "query": {
+          "properties": {
+            "description": {
+              "type": "text"
+            },
+            "filters": {
+              "enabled": false,
+              "type": "object"
+            },
+            "query": {
+              "properties": {
+                "language": {
+                  "type": "keyword"
+                },
+                "query": {
+                  "index": false,
+                  "type": "keyword"
+                }
+              }
+            },
+            "timefilter": {
+              "enabled": false,
+              "type": "object"
             },
             "title": {
               "type": "text"
             }
           }
         },
+        "references": {
+          "properties": {
+            "id": {
+              "type": "keyword"
+            },
+            "name": {
+              "type": "keyword"
+            },
+            "type": {
+              "type": "keyword"
+            }
+          },
+          "type": "nested"
+        },
+        "sample-data-telemetry": {
+          "properties": {
+            "installCount": {
+              "type": "long"
+            },
+            "unInstallCount": {
+              "type": "long"
+            }
+          }
+        },
         "search": {
           "properties": {
             "columns": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "description": {
               "type": "text"
             },
+            "grid": {
+              "enabled": false,
+              "type": "object"
+            },
+            "hideChart": {
+              "doc_values": false,
+              "index": false,
+              "type": "boolean"
+            },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "sort": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
@@ -146,16 +337,100 @@
             }
           }
         },
+        "search-telemetry": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "server": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "telemetry": {
           "properties": {
-            "uuid": {
+            "allowChangingOptInStatus": {
+              "type": "boolean"
+            },
+            "enabled": {
+              "type": "boolean"
+            },
+            "lastReported": {
+              "type": "date"
+            },
+            "lastVersionChecked": {
+              "type": "keyword"
+            },
+            "reportFailureCount": {
+              "type": "integer"
+            },
+            "reportFailureVersion": {
               "type": "keyword"
+            },
+            "sendUsageFrom": {
+              "type": "keyword"
+            },
+            "userHasSeenNotice": {
+              "type": "boolean"
+            }
+          }
+        },
+        "timelion-sheet": {
+          "properties": {
+            "description": {
+              "type": "text"
+            },
+            "hits": {
+              "type": "integer"
+            },
+            "kibanaSavedObjectMeta": {
+              "properties": {
+                "searchSourceJSON": {
+                  "type": "text"
+                }
+              }
+            },
+            "timelion_chart_height": {
+              "type": "integer"
+            },
+            "timelion_columns": {
+              "type": "integer"
+            },
+            "timelion_interval": {
+              "type": "keyword"
+            },
+            "timelion_other_interval": {
+              "type": "keyword"
+            },
+            "timelion_rows": {
+              "type": "integer"
+            },
+            "timelion_sheet": {
+              "type": "text"
+            },
+            "title": {
+              "type": "text"
+            },
+            "version": {
+              "type": "integer"
             }
           }
         },
         "type": {
           "type": "keyword"
         },
+        "ui-counter": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
+        "ui-metric": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
         "updated_at": {
           "type": "date"
         },
@@ -171,13 +446,21 @@
               "type": "date"
             },
             "url": {
-              "type": "text",
               "fields": {
                 "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 2048
+                  "ignore_above": 2048,
+                  "type": "keyword"
                 }
-              }
+              },
+              "type": "text"
+            }
+          }
+        },
+        "usage-counters": {
+          "dynamic": "false",
+          "properties": {
+            "domainId": {
+              "type": "keyword"
             }
           }
         },
@@ -189,28 +472,43 @@
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
-            "savedSearchId": {
+            "savedSearchRefName": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
             "uiStateJSON": {
+              "index": false,
               "type": "text"
             },
             "version": {
               "type": "integer"
             },
             "visState": {
+              "index": false,
               "type": "text"
             }
           }
         }
       }
+    },
+    "settings": {
+      "index": {
+        "auto_expand_replicas": "0-1",
+        "number_of_replicas": "0",
+        "number_of_shards": "1",
+        "priority": "10",
+        "refresh_interval": "1s",
+        "routing_partition_size": "1"
+      }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/search/data.json b/test/api_integration/fixtures/es_archiver/management/saved_objects/search/data.json
new file mode 100644
index 0000000000000..6402a255afd37
--- /dev/null
+++ b/test/api_integration/fixtures/es_archiver/management/saved_objects/search/data.json
@@ -0,0 +1,227 @@
+{
+  "type": "doc",
+  "value": {
+    "id": "timelion-sheet:190f3e90-2ec3-11e8-ba48-69fc4e41e1f6",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
+      "timelion-sheet": {
+        "description": "",
+        "hits": 0,
+        "timelion_chart_height": 275,
+        "timelion_columns": 2,
+        "timelion_interval": "auto",
+        "timelion_rows": 2,
+        "timelion_sheet": [
+          ".es(*)"
+        ],
+        "title": "New TimeLion Sheet",
+        "version": 1
+      },
+      "type": "timelion-sheet",
+      "updated_at": "2018-03-23T17:53:30.872Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "index-pattern:8963ca30-3224-11e8-a572-ffca06da1357",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "index-pattern": {
+        "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]",
+        "title": "saved_objects*"
+      },
+      "migrationVersion": {
+        "index-pattern": "7.11.0"
+      },
+      "references": [
+      ],
+      "type": "index-pattern",
+      "updated_at": "2018-03-28T01:08:34.290Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "config:7.0.0-alpha1",
+    "index": ".kibana",
+    "source": {
+      "config": {
+        "buildNum": 8467,
+        "defaultIndex": "8963ca30-3224-11e8-a572-ffca06da1357",
+        "telemetry:optIn": false
+      },
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "config": "7.13.0"
+      },
+      "references": [
+      ],
+      "type": "config",
+      "updated_at": "2018-03-28T01:08:39.248Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "search:960372e0-3224-11e8-a572-ffca06da1357",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "search": "7.9.3"
+      },
+      "references": [
+        {
+          "id": "8963ca30-3224-11e8-a572-ffca06da1357",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "search": {
+        "columns": [
+          "_source"
+        ],
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"id:3\",\"language\":\"lucene\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "sort": [
+          [
+            "_score",
+            "desc"
+          ]
+        ],
+        "title": "OneRecord",
+        "version": 1
+      },
+      "type": "search",
+      "updated_at": "2018-03-28T01:08:55.182Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:a42c0580-3224-11e8-a572-ffca06da1357",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "960372e0-3224-11e8-a572-ffca06da1357",
+          "name": "search_0",
+          "type": "search"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-03-28T01:09:18.936Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}"
+        },
+        "savedSearchRefName": "search_0",
+        "title": "VisualizationFromSavedSearch",
+        "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}",
+        "version": 1,
+        "visState": "{\"title\":\"VisualizationFromSavedSearch\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\",\"showToolbar\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:add810b0-3224-11e8-a572-ffca06da1357",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "8963ca30-3224-11e8-a572-ffca06da1357",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-03-28T01:09:35.163Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Visualization",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Visualization\",\"type\":\"metric\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"type\":\"metric\",\"metric\":{\"percentageMode\":false,\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"metricColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"labels\":{\"show\":true},\"invertColors\":false,\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:b70c7ae0-3224-11e8-a572-ffca06da1357",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[{\"version\":\"7.0.0-alpha1\",\"gridData\":{\"w\":24,\"h\":15,\"x\":0,\"y\":0,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_0\"},{\"version\":\"7.0.0-alpha1\",\"gridData\":{\"w\":24,\"h\":15,\"x\":24,\"y\":0,\"i\":\"2\"},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"}]",
+        "timeRestore": false,
+        "title": "Dashboard",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "add810b0-3224-11e8-a572-ffca06da1357",
+          "name": "panel_0",
+          "type": "visualization"
+        },
+        {
+          "id": "a42c0580-3224-11e8-a572-ffca06da1357",
+          "name": "panel_1",
+          "type": "visualization"
+        }
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-03-28T01:09:50.606Z"
+    },
+    "type": "_doc"
+  }
+}
\ No newline at end of file
diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/search/data.json.gz b/test/api_integration/fixtures/es_archiver/management/saved_objects/search/data.json.gz
deleted file mode 100644
index 0834567abb66b..0000000000000
Binary files a/test/api_integration/fixtures/es_archiver/management/saved_objects/search/data.json.gz and /dev/null differ
diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/search/mappings.json b/test/api_integration/fixtures/es_archiver/management/saved_objects/search/mappings.json
index 7a6d752eafb08..7699a72ff7120 100644
--- a/test/api_integration/fixtures/es_archiver/management/saved_objects/search/mappings.json
+++ b/test/api_integration/fixtures/es_archiver/management/saved_objects/search/mappings.json
@@ -2,169 +2,335 @@
   "type": "index",
   "value": {
     "aliases": {
+      ".kibana_$KIBANA_PACKAGE_VERSION": {},
       ".kibana": {}
     },
-    "index": ".kibana_1",
-    "settings": {
-      "index": {
-        "number_of_shards": "1",
-        "auto_expand_replicas": "0-1",
-        "number_of_replicas": "0"
-      }
-    },
+    "index": ".kibana_$KIBANA_PACKAGE_VERSION_001",
     "mappings": {
+      "_meta": {
+        "migrationMappingPropertyHashes": {
+          "application_usage_daily": "43b8830d5d0df85a6823d290885fc9fd",
+          "application_usage_totals": "3d1b76c39bfb2cc8296b024d73854724",
+          "application_usage_transactional": "3d1b76c39bfb2cc8296b024d73854724",
+          "config": "c63748b75f39d0c54de12d12c1ccbc20",
+          "core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724",
+          "coreMigrationVersion": "2f4316de49999235636386fe51dc06c1",
+          "dashboard": "40554caf09725935e2c02e02563a2d07",
+          "index-pattern": "45915a1ad866812242df474eb0479052",
+          "kql-telemetry": "d12a98a6f19a2d273696597547e064ee",
+          "legacy-url-alias": "6155300fd11a00e23d5cbaa39f0fce0a",
+          "migrationVersion": "4a1746014a75ade3a714e1db5763276f",
+          "namespace": "2f4316de49999235636386fe51dc06c1",
+          "namespaces": "2f4316de49999235636386fe51dc06c1",
+          "originId": "2f4316de49999235636386fe51dc06c1",
+          "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9",
+          "references": "7997cf5a56cc02bdc9c93361bde732b0",
+          "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4",
+          "search": "db2c00e39b36f40930a3b9fc71c823e1",
+          "search-telemetry": "3d1b76c39bfb2cc8296b024d73854724",
+          "telemetry": "36a616f7026dfa617d6655df850fe16d",
+          "timelion-sheet": "9a2a2748877c7a7b582fef201ab1d4cf",
+          "type": "2f4316de49999235636386fe51dc06c1",
+          "ui-counter": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "updated_at": "00da57df13e94e9d98437d13ace4bfe0",
+          "url": "c7f66a0df8b1b52f17c28c4adb111105",
+          "usage-counters": "8cc260bdceffec4ffc3ad165c97dc1b4",
+          "visualization": "f819cf6636b75c9e76ba733a0c6ef355"
+        }
+      },
       "dynamic": "strict",
       "properties": {
+        "application_usage_daily": {
+          "dynamic": "false",
+          "properties": {
+            "timestamp": {
+              "type": "date"
+            }
+          }
+        },
+        "application_usage_totals": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "application_usage_transactional": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "config": {
-          "dynamic": "true",
+          "dynamic": "false",
           "properties": {
             "buildNum": {
               "type": "keyword"
-            },
-            "defaultIndex": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 256
-                }
-              }
-            },
-            "telemetry:optIn": {
-              "type": "boolean"
             }
           }
         },
+        "core-usage-stats": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "coreMigrationVersion": {
+          "type": "keyword"
+        },
         "dashboard": {
           "properties": {
             "description": {
               "type": "text"
             },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "optionsJSON": {
+              "index": false,
               "type": "text"
             },
             "panelsJSON": {
+              "index": false,
               "type": "text"
             },
             "refreshInterval": {
               "properties": {
                 "display": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "keyword"
                 },
                 "pause": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "boolean"
                 },
                 "section": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 },
                 "value": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 }
               }
             },
             "timeFrom": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "timeRestore": {
+              "doc_values": false,
+              "index": false,
               "type": "boolean"
             },
             "timeTo": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
-            "uiStateJSON": {
-              "type": "text"
-            },
             "version": {
               "type": "integer"
             }
           }
         },
         "graph-workspace": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "index-pattern": {
+          "dynamic": "false",
           "properties": {
-            "description": {
+            "title": {
               "type": "text"
             },
-            "kibanaSavedObjectMeta": {
-              "properties": {
-                "searchSourceJSON": {
-                  "type": "text"
-                }
-              }
+            "type": {
+              "type": "keyword"
+            }
+          }
+        },
+        "kql-telemetry": {
+          "properties": {
+            "optInCount": {
+              "type": "long"
             },
-            "numLinks": {
-              "type": "integer"
+            "optOutCount": {
+              "type": "long"
+            }
+          }
+        },
+        "legacy-url-alias": {
+          "dynamic": "false",
+          "properties": {
+            "disabled": {
+              "type": "boolean"
             },
-            "numVertices": {
-              "type": "integer"
+            "sourceId": {
+              "type": "keyword"
             },
-            "title": {
+            "targetType": {
+              "type": "keyword"
+            }
+          }
+        },
+        "migrationVersion": {
+          "dynamic": "true",
+          "properties": {
+            "config": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
               "type": "text"
             },
-            "version": {
-              "type": "integer"
+            "dashboard": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            },
+            "index-pattern": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            },
+            "search": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
             },
-            "wsState": {
+            "visualization": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
               "type": "text"
             }
           }
         },
-        "index-pattern": {
+        "namespace": {
+          "type": "keyword"
+        },
+        "namespaces": {
+          "type": "keyword"
+        },
+        "originId": {
+          "type": "keyword"
+        },
+        "query": {
           "properties": {
-            "fieldFormatMap": {
+            "description": {
               "type": "text"
             },
-            "fields": {
-              "type": "text"
+            "filters": {
+              "enabled": false,
+              "type": "object"
             },
-            "intervalName": {
-              "type": "keyword"
+            "query": {
+              "properties": {
+                "language": {
+                  "type": "keyword"
+                },
+                "query": {
+                  "index": false,
+                  "type": "keyword"
+                }
+              }
             },
-            "notExpandable": {
-              "type": "boolean"
+            "timefilter": {
+              "enabled": false,
+              "type": "object"
             },
-            "sourceFilters": {
+            "title": {
               "type": "text"
+            }
+          }
+        },
+        "references": {
+          "properties": {
+            "id": {
+              "type": "keyword"
             },
-            "timeFieldName": {
+            "name": {
               "type": "keyword"
             },
-            "title": {
-              "type": "text"
+            "type": {
+              "type": "keyword"
+            }
+          },
+          "type": "nested"
+        },
+        "sample-data-telemetry": {
+          "properties": {
+            "installCount": {
+              "type": "long"
+            },
+            "unInstallCount": {
+              "type": "long"
             }
           }
         },
         "search": {
           "properties": {
             "columns": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "description": {
               "type": "text"
             },
+            "grid": {
+              "enabled": false,
+              "type": "object"
+            },
+            "hideChart": {
+              "doc_values": false,
+              "index": false,
+              "type": "boolean"
+            },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "sort": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
@@ -175,10 +341,39 @@
             }
           }
         },
+        "search-telemetry": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "server": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "telemetry": {
           "properties": {
-            "uuid": {
+            "allowChangingOptInStatus": {
+              "type": "boolean"
+            },
+            "enabled": {
+              "type": "boolean"
+            },
+            "lastReported": {
+              "type": "date"
+            },
+            "lastVersionChecked": {
+              "type": "keyword"
+            },
+            "reportFailureCount": {
+              "type": "integer"
+            },
+            "reportFailureVersion": {
               "type": "keyword"
+            },
+            "sendUsageFrom": {
+              "type": "keyword"
+            },
+            "userHasSeenNotice": {
+              "type": "boolean"
             }
           }
         },
@@ -226,6 +421,20 @@
         "type": {
           "type": "keyword"
         },
+        "ui-counter": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
+        "ui-metric": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
         "updated_at": {
           "type": "date"
         },
@@ -241,13 +450,21 @@
               "type": "date"
             },
             "url": {
-              "type": "text",
               "fields": {
                 "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 2048
+                  "ignore_above": 2048,
+                  "type": "keyword"
                 }
-              }
+              },
+              "type": "text"
+            }
+          }
+        },
+        "usage-counters": {
+          "dynamic": "false",
+          "properties": {
+            "domainId": {
+              "type": "keyword"
             }
           }
         },
@@ -259,28 +476,43 @@
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
-            "savedSearchId": {
+            "savedSearchRefName": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
             "uiStateJSON": {
+              "index": false,
               "type": "text"
             },
             "version": {
               "type": "integer"
             },
             "visState": {
+              "index": false,
               "type": "text"
             }
           }
         }
       }
+    },
+    "settings": {
+      "index": {
+        "auto_expand_replicas": "0-1",
+        "number_of_replicas": "0",
+        "number_of_shards": "1",
+        "priority": "10",
+        "refresh_interval": "1s",
+        "routing_partition_size": "1"
+      }
     }
   }
 }
\ No newline at end of file
diff --git a/test/functional/apps/discover/_runtime_fields_editor.ts b/test/functional/apps/discover/_runtime_fields_editor.ts
index fd2ca4dd4b5cf..648fa3efe337c 100644
--- a/test/functional/apps/discover/_runtime_fields_editor.ts
+++ b/test/functional/apps/discover/_runtime_fields_editor.ts
@@ -31,7 +31,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
     await fieldEditor.save();
   };
 
-  describe('discover integration with runtime fields editor', function describeIndexTests() {
+  describe.skip('discover integration with runtime fields editor', function describeIndexTests() {
     before(async function () {
       await esArchiver.load('test/functional/fixtures/es_archiver/discover');
       await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional');
@@ -104,6 +104,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
       });
     });
 
+    // flaky https://github.com/elastic/kibana/issues/100966
     it('doc view includes runtime fields', async function () {
       // navigate to doc view
       const table = await PageObjects.discover.getDocTable();
diff --git a/test/functional/apps/discover/_sidebar.ts b/test/functional/apps/discover/_sidebar.ts
index d8701261126c4..8179f4e44e8b8 100644
--- a/test/functional/apps/discover/_sidebar.ts
+++ b/test/functional/apps/discover/_sidebar.ts
@@ -14,7 +14,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
   const PageObjects = getPageObjects(['common', 'discover', 'timePicker']);
   const testSubjects = getService('testSubjects');
 
-  describe('discover sidebar', function describeIndexTests() {
+  // Failing: See https://github.com/elastic/kibana/issues/101449
+  describe.skip('discover sidebar', function describeIndexTests() {
     before(async function () {
       await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional');
       await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/discover');
diff --git a/test/functional/config.js b/test/functional/config.js
index 4a6791a3bc62f..eac21e5a45618 100644
--- a/test/functional/config.js
+++ b/test/functional/config.js
@@ -97,6 +97,9 @@ export default async function ({ readConfigFile }) {
         pathname: '/app/home',
         hash: '/',
       },
+      observabilityCases: {
+        pathname: '/app/observability/cases',
+      },
     },
     junit: {
       reportName: 'Chrome UI Functional Tests',
diff --git a/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json b/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json
new file mode 100644
index 0000000000000..139da89e58d12
--- /dev/null
+++ b/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json
@@ -0,0 +1,3471 @@
+{
+  "type": "doc",
+  "value": {
+    "id": "search:a16d1990-3dca-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "search": "7.9.3"
+      },
+      "references": [
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "search": {
+        "columns": [
+          "animal",
+          "isDog",
+          "name",
+          "sound",
+          "weightLbs"
+        ],
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"lucene\",\"query\":\"weightLbs:>40\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "sort": [
+          [
+            "weightLbs",
+            "desc"
+          ]
+        ],
+        "title": "animal weights",
+        "version": 1
+      },
+      "type": "search",
+      "updated_at": "2018-04-11T20:55:26.317Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "config:6.3.0",
+    "index": ".kibana",
+    "source": {
+      "config": {
+        "buildNum": 8467,
+        "defaultIndex": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c"
+      },
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "config": "7.13.0"
+      },
+      "references": [
+      ],
+      "type": "config",
+      "updated_at": "2018-04-11T20:43:55.434Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:61c58ad0-3dd3-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"animal\",\"value\":\"dog\",\"params\":{\"query\":\"dog\",\"type\":\"phrase\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"animal\":{\"query\":\"dog\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"w\":24,\"h\":15,\"x\":0,\"y\":0,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"w\":24,\"h\":15,\"x\":24,\"y\":0,\"i\":\"2\"},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"}]",
+        "refreshInterval": {
+          "display": "Off",
+          "pause": false,
+          "value": 0
+        },
+        "timeFrom": "Mon Apr 09 2018 17:56:08 GMT-0400",
+        "timeRestore": true,
+        "timeTo": "Wed Apr 11 2018 17:56:08 GMT-0400",
+        "title": "dashboard with filter",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "50643b60-3dd3-11e8-b2b9-5d5dc1715159",
+          "name": "1:panel_1",
+          "type": "visualization"
+        },
+        {
+          "id": "a16d1990-3dca-11e8-8660-4d65aa086b3c",
+          "name": "2:panel_2",
+          "type": "search"
+        }
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T21:57:52.253Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:2ae34a60-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"w\":24,\"h\":15,\"x\":0,\"y\":0,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"w\":24,\"h\":15,\"x\":24,\"y\":0,\"i\":\"2\"},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"}]",
+        "timeRestore": false,
+        "title": "couple panels",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "145ced90-3dcb-11e8-8660-4d65aa086b3c",
+          "name": "1:panel_1",
+          "type": "visualization"
+        },
+        {
+          "id": "e2023110-3dcb-11e8-8660-4d65aa086b3c",
+          "name": "2:panel_2",
+          "type": "visualization"
+        }
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:03:29.670Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:76d03330-3dd3-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "and_descriptions_has_underscores",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "dashboard_with_underscores",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T21:58:27.555Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:9b780cd0-3dd3-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "* hi & $%!!@# 漢字 ^--=++[]{};'~`~<>?,./:\";'\\|\\\\ special chars",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:00:07.322Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:6c0b16e0-3dd3-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "dashboard-name-has-dashes",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T21:58:09.486Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:19523860-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "im empty too",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:03:00.198Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:14616b50-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "im empty",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:02:51.909Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:33bb8ad0-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"2\"},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"3\"},\"panelIndex\":\"3\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"}]",
+        "timeRestore": false,
+        "title": "few panels",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "145ced90-3dcb-11e8-8660-4d65aa086b3c",
+          "name": "1:panel_1",
+          "type": "visualization"
+        },
+        {
+          "id": "e2023110-3dcb-11e8-8660-4d65aa086b3c",
+          "name": "2:panel_2",
+          "type": "visualization"
+        },
+        {
+          "id": "4b5d6ef0-3dcb-11e8-8660-4d65aa086b3c",
+          "name": "3:panel_3",
+          "type": "visualization"
+        }
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:03:44.509Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:60659030-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "zz 2",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:04:59.443Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:65227c00-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "zz 3",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:05:07.392Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:6803a2f0-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "zz 4",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:05:12.223Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:6b18f940-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "zz 5",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:05:17.396Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:6e12ff60-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "zz 6",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:05:22.390Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:4f0fd980-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "zz",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:04:30.360Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:3de0bda0-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "1",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:04:01.530Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:46c8b580-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "2",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:04:16.472Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:708fe640-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "zz 7",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:05:26.564Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:7b8d50a0-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "Hi i have a lot of words in my dashboard name! It's pretty long i wonder what it'll look like",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:05:45.002Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:7e42d3b0-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "bye",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:05:49.547Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:846988b0-3dd4-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[]",
+        "timeRestore": false,
+        "title": "last",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-11T22:05:59.867Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:cbd3bc30-3e5a-11e8-9fc3-39e49624228e",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"weightLbs:<50\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"negate\":true,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"name.keyword\",\"value\":\"Fee Fee\",\"params\":{\"query\":\"Fee Fee\",\"type\":\"phrase\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"name.keyword\":{\"query\":\"Fee Fee\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":true,\"useMargins\":true,\"hidePanelTitles\":true}",
+        "panelsJSON": "[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"2\"},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"3\"},\"panelIndex\":\"3\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"}]",
+        "timeRestore": false,
+        "title": "bug",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "771b4f10-3e59-11e8-9fc3-39e49624228e",
+          "name": "1:panel_1",
+          "type": "visualization"
+        },
+        {
+          "id": "befdb6b0-3e59-11e8-9fc3-39e49624228e",
+          "name": "2:panel_2",
+          "type": "visualization"
+        },
+        {
+          "id": "4c0c3f90-3e5a-11e8-9fc3-39e49624228e",
+          "name": "3:panel_3",
+          "type": "visualization"
+        }
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-12T14:07:12.243Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:5bac3a80-3e5b-11e8-9fc3-39e49624228e",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "dashboard with scripted filter, negated filter and query",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"weightLbs:<50\"},\"filter\":[{\"$state\":{\"store\":\"appState\"},\"meta\":{\"alias\":null,\"disabled\":false,\"key\":\"name.keyword\",\"negate\":true,\"params\":{\"query\":\"Fee Fee\",\"type\":\"phrase\"},\"type\":\"phrase\",\"value\":\"Fee Fee\",\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"name.keyword\":{\"query\":\"Fee Fee\",\"type\":\"phrase\"}}}},{\"$state\":{\"store\":\"appState\"},\"meta\":{\"alias\":\"is dog\",\"disabled\":false,\"field\":\"isDog\",\"key\":\"isDog\",\"negate\":false,\"params\":{\"value\":true},\"type\":\"phrase\",\"value\":\"true\",\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index\"},\"script\":{\"script\":{\"inline\":\"boolean compare(Supplier s, def v) {return s.get() == v;}compare(() -> { return doc['animal.keyword'].value == 'dog' }, params.value);\",\"lang\":\"painless\",\"params\":{\"value\":true}}}}],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":true,\"hidePanelTitles\":false,\"useMargins\":true}",
+        "panelsJSON": "[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"3\"},\"panelIndex\":\"3\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"4\"},\"panelIndex\":\"4\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"}]",
+        "refreshInterval": {
+          "display": "Off",
+          "pause": false,
+          "section": 0,
+          "value": 0
+        },
+        "timeFrom": "Wed Apr 12 2017 10:06:21 GMT-0400",
+        "timeRestore": true,
+        "timeTo": "Thu Apr 12 2018 10:06:21 GMT-0400",
+        "title": "filters",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "771b4f10-3e59-11e8-9fc3-39e49624228e",
+          "name": "1:panel_1",
+          "type": "visualization"
+        },
+        {
+          "id": "4c0c3f90-3e5a-11e8-9fc3-39e49624228e",
+          "name": "3:panel_3",
+          "type": "visualization"
+        },
+        {
+          "id": "50643b60-3dd3-11e8-b2b9-5d5dc1715159",
+          "name": "4:panel_4",
+          "type": "visualization"
+        }
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-12T14:11:13.576Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "index-pattern:f908c8e0-3e6d-11e8-bbb9-e15942d5d48c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "index-pattern": {
+        "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"activity level\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"barking level\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"breed\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"breed.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"size\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"size.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"trainability\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]",
+        "title": "dogbreeds"
+      },
+      "migrationVersion": {
+        "index-pattern": "7.11.0"
+      },
+      "references": [
+      ],
+      "type": "index-pattern",
+      "updated_at": "2018-04-12T16:24:29.357Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:5e085850-3e6e-11e8-bbb9-e15942d5d48c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "f908c8e0-3e6d-11e8-bbb9-e15942d5d48c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-12T16:27:17.973Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "non timebased line chart - dog data",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"non timebased line chart - dog data\",\"type\":\"line\",\"params\":{\"type\":\"line\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Max trainability\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"line\",\"mode\":\"normal\",\"data\":{\"label\":\"Max trainability\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true},{\"show\":true,\"mode\":\"normal\",\"type\":\"line\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"data\":{\"id\":\"3\",\"label\":\"Max barking level\"},\"valueAxis\":\"ValueAxis-1\"},{\"show\":true,\"mode\":\"normal\",\"type\":\"line\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"data\":{\"id\":\"4\",\"label\":\"Max activity level\"},\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"fittingFunction\":\"zero\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"trainability\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"breed.keyword\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"barking level\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"activity level\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:a5d56330-3e6e-11e8-bbb9-e15942d5d48c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "I have two visualizations that are created off a non time based index",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+        "panelsJSON": "[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"w\":24,\"h\":15,\"x\":0,\"y\":0,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"w\":24,\"h\":15,\"x\":24,\"y\":0,\"i\":\"2\"},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"}]",
+        "timeRestore": false,
+        "title": "Non time based",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "5e085850-3e6e-11e8-bbb9-e15942d5d48c",
+          "name": "1:panel_1",
+          "type": "visualization"
+        },
+        {
+          "id": "8bc8d6c0-3e6e-11e8-bbb9-e15942d5d48c",
+          "name": "2:panel_2",
+          "type": "visualization"
+        }
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-12T16:29:18.435Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:d2525040-3dcd-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "I have one of every visualization type since the last time I was created!",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}",
+        "panelsJSON": "[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"2\"},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"3\"},\"panelIndex\":\"3\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":15,\"w\":24,\"h\":15,\"i\":\"4\"},\"panelIndex\":\"4\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":30,\"w\":24,\"h\":15,\"i\":\"5\"},\"panelIndex\":\"5\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":30,\"w\":24,\"h\":15,\"i\":\"6\"},\"panelIndex\":\"6\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":45,\"w\":24,\"h\":15,\"i\":\"7\"},\"panelIndex\":\"7\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_7\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":45,\"w\":24,\"h\":15,\"i\":\"8\"},\"panelIndex\":\"8\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_8\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":60,\"w\":24,\"h\":15,\"i\":\"9\"},\"panelIndex\":\"9\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":60,\"w\":24,\"h\":15,\"i\":\"10\"},\"panelIndex\":\"10\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_10\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":75,\"w\":24,\"h\":15,\"i\":\"11\"},\"panelIndex\":\"11\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_11\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":75,\"w\":24,\"h\":15,\"i\":\"12\"},\"panelIndex\":\"12\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_12\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":90,\"w\":24,\"h\":15,\"i\":\"13\"},\"panelIndex\":\"13\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":90,\"w\":24,\"h\":15,\"i\":\"14\"},\"panelIndex\":\"14\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_14\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":105,\"w\":24,\"h\":15,\"i\":\"15\"},\"panelIndex\":\"15\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_15\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":105,\"w\":24,\"h\":15,\"i\":\"16\"},\"panelIndex\":\"16\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_16\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":120,\"w\":24,\"h\":15,\"i\":\"17\"},\"panelIndex\":\"17\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_17\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":120,\"w\":24,\"h\":15,\"i\":\"18\"},\"panelIndex\":\"18\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_18\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":135,\"w\":24,\"h\":15,\"i\":\"19\"},\"panelIndex\":\"19\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_19\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":135,\"w\":24,\"h\":15,\"i\":\"20\"},\"panelIndex\":\"20\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_20\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":150,\"w\":24,\"h\":15,\"i\":\"21\"},\"panelIndex\":\"21\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_21\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":150,\"w\":24,\"h\":15,\"i\":\"22\"},\"panelIndex\":\"22\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_22\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":165,\"w\":24,\"h\":15,\"i\":\"23\"},\"panelIndex\":\"23\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_23\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"x\":24,\"y\":165,\"w\":24,\"h\":15,\"i\":\"24\"},\"panelIndex\":\"24\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_24\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"x\":0,\"y\":180,\"w\":24,\"h\":15,\"i\":\"25\"},\"panelIndex\":\"25\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_25\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"x\":24,\"y\":180,\"w\":24,\"h\":15,\"i\":\"26\"},\"panelIndex\":\"26\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_26\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":195,\"w\":24,\"h\":15,\"i\":\"27\"},\"panelIndex\":\"27\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_27\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":195,\"w\":24,\"h\":15,\"i\":\"28\"},\"panelIndex\":\"28\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_28\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":210,\"w\":24,\"h\":15,\"i\":\"29\"},\"panelIndex\":\"29\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_29\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"w\":24,\"h\":15,\"x\":24,\"y\":210,\"i\":\"30\"},\"panelIndex\":\"30\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_30\"}]",
+        "refreshInterval": {
+          "display": "Off",
+          "pause": false,
+          "value": 0
+        },
+        "timeFrom": "Mon Apr 09 2018 17:56:08 GMT-0400",
+        "timeRestore": true,
+        "timeTo": "Wed Apr 11 2018 17:56:08 GMT-0400",
+        "title": "dashboard with everything",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "e6140540-3dca-11e8-8660-4d65aa086b3c",
+          "name": "1:panel_1",
+          "type": "visualization"
+        },
+        {
+          "id": "3525b840-3dcb-11e8-8660-4d65aa086b3c",
+          "name": "2:panel_2",
+          "type": "visualization"
+        },
+        {
+          "id": "4b5d6ef0-3dcb-11e8-8660-4d65aa086b3c",
+          "name": "3:panel_3",
+          "type": "visualization"
+        },
+        {
+          "id": "37a541c0-3dcc-11e8-8660-4d65aa086b3c",
+          "name": "4:panel_4",
+          "type": "visualization"
+        },
+        {
+          "id": "ffa2e0c0-3dcb-11e8-8660-4d65aa086b3c",
+          "name": "5:panel_5",
+          "type": "visualization"
+        },
+        {
+          "id": "e2023110-3dcb-11e8-8660-4d65aa086b3c",
+          "name": "6:panel_6",
+          "type": "visualization"
+        },
+        {
+          "id": "145ced90-3dcb-11e8-8660-4d65aa086b3c",
+          "name": "7:panel_7",
+          "type": "visualization"
+        },
+        {
+          "id": "2d1b1620-3dcd-11e8-8660-4d65aa086b3c",
+          "name": "8:panel_8",
+          "type": "visualization"
+        },
+        {
+          "id": "42535e30-3dcd-11e8-8660-4d65aa086b3c",
+          "name": "9:panel_9",
+          "type": "visualization"
+        },
+        {
+          "id": "42535e30-3dcd-11e8-8660-4d65aa086b3c",
+          "name": "10:panel_10",
+          "type": "visualization"
+        },
+        {
+          "id": "4c0f47e0-3dcd-11e8-8660-4d65aa086b3c",
+          "name": "11:panel_11",
+          "type": "visualization"
+        },
+        {
+          "id": "11ae2bd0-3dcc-11e8-8660-4d65aa086b3c",
+          "name": "12:panel_12",
+          "type": "visualization"
+        },
+        {
+          "id": "3fe22200-3dcb-11e8-8660-4d65aa086b3c",
+          "name": "13:panel_13",
+          "type": "visualization"
+        },
+        {
+          "id": "4ca00ba0-3dcc-11e8-8660-4d65aa086b3c",
+          "name": "14:panel_14",
+          "type": "visualization"
+        },
+        {
+          "id": "78803be0-3dcd-11e8-8660-4d65aa086b3c",
+          "name": "15:panel_15",
+          "type": "visualization"
+        },
+        {
+          "id": "b92ae920-3dcc-11e8-8660-4d65aa086b3c",
+          "name": "16:panel_16",
+          "type": "visualization"
+        },
+        {
+          "id": "e4d8b430-3dcc-11e8-8660-4d65aa086b3c",
+          "name": "17:panel_17",
+          "type": "visualization"
+        },
+        {
+          "id": "f81134a0-3dcc-11e8-8660-4d65aa086b3c",
+          "name": "18:panel_18",
+          "type": "visualization"
+        },
+        {
+          "id": "cc43fab0-3dcc-11e8-8660-4d65aa086b3c",
+          "name": "19:panel_19",
+          "type": "visualization"
+        },
+        {
+          "id": "02a2e4e0-3dcd-11e8-8660-4d65aa086b3c",
+          "name": "20:panel_20",
+          "type": "visualization"
+        },
+        {
+          "id": "df815d20-3dcc-11e8-8660-4d65aa086b3c",
+          "name": "21:panel_21",
+          "type": "visualization"
+        },
+        {
+          "id": "c40f4d40-3dcc-11e8-8660-4d65aa086b3c",
+          "name": "22:panel_22",
+          "type": "visualization"
+        },
+        {
+          "id": "7fda8ee0-3dcd-11e8-8660-4d65aa086b3c",
+          "name": "23:panel_23",
+          "type": "visualization"
+        },
+        {
+          "id": "a16d1990-3dca-11e8-8660-4d65aa086b3c",
+          "name": "24:panel_24",
+          "type": "search"
+        },
+        {
+          "id": "be5accf0-3dca-11e8-8660-4d65aa086b3c",
+          "name": "25:panel_25",
+          "type": "search"
+        },
+        {
+          "id": "ca5ada40-3dca-11e8-8660-4d65aa086b3c",
+          "name": "26:panel_26",
+          "type": "search"
+        },
+        {
+          "id": "771b4f10-3e59-11e8-9fc3-39e49624228e",
+          "name": "27:panel_27",
+          "type": "visualization"
+        },
+        {
+          "id": "5e085850-3e6e-11e8-bbb9-e15942d5d48c",
+          "name": "28:panel_28",
+          "type": "visualization"
+        },
+        {
+          "id": "8bc8d6c0-3e6e-11e8-bbb9-e15942d5d48c",
+          "name": "29:panel_29",
+          "type": "visualization"
+        },
+        {
+          "id": "befdb6b0-3e59-11e8-9fc3-39e49624228e",
+          "name": "30:panel_30",
+          "type": "visualization"
+        }
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-16T16:05:02.915Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:29bd0240-4197-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-16T16:56:53.092Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[{\"meta\":{\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"geo.src\",\"value\":\"CN\",\"params\":{\"query\":\"CN\",\"type\":\"phrase\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"geo.src\":{\"query\":\"CN\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"query\":{\"query\":\"bytes >= 10000\",\"language\":\"kuery\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Kuery: pie bytes with kuery and filter",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Kuery: pie bytes with kuery and filter\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"distinctColors\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"bytes\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "index-pattern:0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "index-pattern": {
+        "fieldFormatMap": "{\"machine.ram\":{\"id\":\"number\",\"params\":{\"pattern\":\"0,0.[000] b\"}}}",
+        "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"count\":2,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":3,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":3,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]",
+        "timeFieldName": "@timestamp",
+        "title": "logstash-*"
+      },
+      "migrationVersion": {
+        "index-pattern": "7.11.0"
+      },
+      "references": [
+      ],
+      "type": "index-pattern",
+      "updated_at": "2018-04-16T16:57:12.263Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "search:55d37a30-4197-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "search": "7.9.3"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        }
+      ],
+      "search": {
+        "columns": [
+          "agent",
+          "bytes",
+          "clientip"
+        ],
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"clientip : 73.14.212.83\",\"language\":\"kuery\"},\"filter\":[{\"meta\":{\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"range\",\"key\":\"bytes\",\"value\":\"100 to 1,000\",\"params\":{\"gte\":100,\"lt\":1000},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"range\":{\"bytes\":{\"gte\":100,\"lt\":1000}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "sort": [
+          [
+            "@timestamp",
+            "desc"
+          ]
+        ],
+        "title": "Bytes and kuery in saved search with filter",
+        "version": 1
+      },
+      "type": "search",
+      "updated_at": "2018-04-16T16:58:07.059Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:b60de070-4197-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "Bytes bytes and more bytes",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}",
+        "panelsJSON": "[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"2\"},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"3\"},\"panelIndex\":\"3\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":15,\"w\":17,\"h\":8,\"i\":\"4\"},\"panelIndex\":\"4\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":30,\"w\":18,\"h\":13,\"i\":\"5\"},\"panelIndex\":\"5\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":37,\"w\":24,\"h\":12,\"i\":\"6\"},\"panelIndex\":\"6\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":18,\"y\":30,\"w\":9,\"h\":7,\"i\":\"7\"},\"panelIndex\":\"7\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_7\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":28,\"y\":23,\"w\":15,\"h\":13,\"i\":\"8\"},\"panelIndex\":\"8\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_8\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":43,\"w\":24,\"h\":15,\"i\":\"9\"},\"panelIndex\":\"9\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":49,\"w\":18,\"h\":12,\"i\":\"10\"},\"panelIndex\":\"10\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_10\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":58,\"w\":24,\"h\":15,\"i\":\"11\"},\"panelIndex\":\"11\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_11\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":61,\"w\":5,\"h\":4,\"i\":\"12\"},\"panelIndex\":\"12\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_12\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":73,\"w\":17,\"h\":6,\"i\":\"13\"},\"panelIndex\":\"13\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":65,\"w\":24,\"h\":15,\"i\":\"14\"},\"panelIndex\":\"14\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_14\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":79,\"w\":24,\"h\":6,\"i\":\"15\"},\"panelIndex\":\"15\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_15\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":80,\"w\":24,\"h\":15,\"i\":\"16\"},\"panelIndex\":\"16\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_16\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":85,\"w\":13,\"h\":11,\"i\":\"17\"},\"panelIndex\":\"17\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_17\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"x\":24,\"y\":95,\"w\":23,\"h\":11,\"i\":\"18\"},\"panelIndex\":\"18\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_18\"}]",
+        "refreshInterval": {
+          "display": "Off",
+          "pause": false,
+          "value": 0
+        },
+        "timeFrom": "Mon Apr 09 2018 17:56:08 GMT-0400",
+        "timeRestore": true,
+        "timeTo": "Wed Apr 11 2018 17:56:08 GMT-0400",
+        "title": "All about those bytes",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "7ff2c4c0-4191-11e8-bb13-d53698fb349a",
+          "name": "1:panel_1",
+          "type": "visualization"
+        },
+        {
+          "id": "03d2afd0-4192-11e8-bb13-d53698fb349a",
+          "name": "2:panel_2",
+          "type": "visualization"
+        },
+        {
+          "id": "63983430-4192-11e8-bb13-d53698fb349a",
+          "name": "3:panel_3",
+          "type": "visualization"
+        },
+        {
+          "id": "0ca8c600-4195-11e8-bb13-d53698fb349a",
+          "name": "4:panel_4",
+          "type": "visualization"
+        },
+        {
+          "id": "c10c6b00-4191-11e8-bb13-d53698fb349a",
+          "name": "5:panel_5",
+          "type": "visualization"
+        },
+        {
+          "id": "760a9060-4190-11e8-bb13-d53698fb349a",
+          "name": "6:panel_6",
+          "type": "visualization"
+        },
+        {
+          "id": "1dcdfe30-4192-11e8-bb13-d53698fb349a",
+          "name": "7:panel_7",
+          "type": "visualization"
+        },
+        {
+          "id": "584c0300-4191-11e8-bb13-d53698fb349a",
+          "name": "8:panel_8",
+          "type": "visualization"
+        },
+        {
+          "id": "b3e70d00-4190-11e8-bb13-d53698fb349a",
+          "name": "9:panel_9",
+          "type": "visualization"
+        },
+        {
+          "id": "df72ad40-4194-11e8-bb13-d53698fb349a",
+          "name": "10:panel_10",
+          "type": "visualization"
+        },
+        {
+          "id": "9bebe980-4192-11e8-bb13-d53698fb349a",
+          "name": "11:panel_11",
+          "type": "visualization"
+        },
+        {
+          "id": "9fb4c670-4194-11e8-bb13-d53698fb349a",
+          "name": "12:panel_12",
+          "type": "visualization"
+        },
+        {
+          "id": "35417e50-4194-11e8-bb13-d53698fb349a",
+          "name": "13:panel_13",
+          "type": "visualization"
+        },
+        {
+          "id": "039e4770-4194-11e8-bb13-d53698fb349a",
+          "name": "14:panel_14",
+          "type": "visualization"
+        },
+        {
+          "id": "76c7f020-4194-11e8-bb13-d53698fb349a",
+          "name": "15:panel_15",
+          "type": "visualization"
+        },
+        {
+          "id": "8090dcb0-4195-11e8-bb13-d53698fb349a",
+          "name": "16:panel_16",
+          "type": "visualization"
+        },
+        {
+          "id": "29bd0240-4197-11e8-bb13-d53698fb349a",
+          "name": "17:panel_17",
+          "type": "visualization"
+        },
+        {
+          "id": "55d37a30-4197-11e8-bb13-d53698fb349a",
+          "name": "18:panel_18",
+          "type": "search"
+        }
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-04-16T17:00:48.503Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:78803be0-3dcd-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:32.127Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Rendering Test: tag cloud",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: tag cloud\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.src\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:3fe22200-3dcb-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:32.130Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Rendering Test: pie",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: pie\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"distinctColors\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"bytes\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:4ca00ba0-3dcc-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:32.131Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Rendering Test: region map",
+        "uiStateJSON": "{\"mapZoom\":2,\"mapCenter\":[8.754794702435618,-9.140625000000002]}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: region map\",\"type\":\"region_map\",\"params\":{\"legendPosition\":\"bottomright\",\"addTooltip\":true,\"colorSchema\":\"Yellow to Red\",\"selectedLayer\":{\"attribution\":\"<p><a href=\\\"http://www.naturalearthdata.com/about/terms-of-use\\\">Made with NaturalEarth</a> | <a href=\\\"https://www.elastic.co/elastic-maps-service\\\">Elastic Maps Service</a></p>&#10;\",\"name\":\"World Countries\",\"weight\":1,\"format\":{\"type\":\"geojson\"},\"url\":\"https://staging-dot-elastic-layer.appspot.com/blob/5715999101812736?elastic_tile_service_tos=agree&my_app_version=6.3.0\",\"fields\":[{\"name\":\"iso2\",\"description\":\"Two letter abbreviation\"},{\"name\":\"iso3\",\"description\":\"Three letter abbreviation\"},{\"name\":\"name\",\"description\":\"Country name\"}],\"created_at\":\"2017-07-31T16:00:19.996450\",\"tags\":[],\"id\":5715999101812736,\"layerId\":\"elastic_maps_service.World Countries\"},\"selectedJoinField\":{\"name\":\"iso2\",\"description\":\"Two letter abbreviation\"},\"isDisplayWarning\":true,\"wms\":{\"enabled\":false,\"options\":{\"format\":\"image/png\",\"transparent\":true},\"baseLayersAreLoaded\":{},\"tmsLayers\":[{\"id\":\"road_map\",\"url\":\"https://tiles-stage.elastic.co/v2/default/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana&my_app_version=6.3.0\",\"minZoom\":0,\"maxZoom\":10,\"attribution\":\"<p>&#169; <a href=\\\"http://www.openstreetmap.org/copyright\\\">OpenStreetMap</a> contributors | <a href=\\\"https://www.elastic.co/elastic-maps-service\\\">Elastic Maps Service</a></p>&#10;\",\"subdomains\":[]}],\"selectedTmsLayer\":{\"id\":\"road_map\",\"url\":\"https://tiles-stage.elastic.co/v2/default/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana&my_app_version=6.3.0\",\"minZoom\":0,\"maxZoom\":10,\"attribution\":\"<p>&#169; <a href=\\\"http://www.openstreetmap.org/copyright\\\">OpenStreetMap</a> contributors | <a href=\\\"https://www.elastic.co/elastic-maps-service\\\">Elastic Maps Service</a></p>&#10;\",\"subdomains\":[]}},\"mapZoom\":2,\"mapCenter\":[0,0],\"outlineWeight\":1,\"showAllShapes\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.src\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:11ae2bd0-3dcc-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:32.133Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Rendering Test: metric",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: metric\",\"type\":\"metric\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"type\":\"metric\",\"metric\":{\"percentageMode\":false,\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"metricColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"labels\":{\"show\":true},\"invertColors\":false,\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"bytes\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:145ced90-3dcb-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:32.134Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Rendering Test: heatmap",
+        "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 15\":\"rgb(247,252,245)\",\"15 - 30\":\"rgb(199,233,192)\",\"30 - 45\":\"rgb(116,196,118)\",\"45 - 60\":\"rgb(35,139,69)\"}}}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: heatmap\",\"type\":\"heatmap\",\"params\":{\"type\":\"heatmap\",\"addTooltip\":true,\"addLegend\":true,\"enableHover\":false,\"legendPosition\":\"right\",\"times\":[],\"colorsNumber\":4,\"colorSchema\":\"Greens\",\"setColorRange\":false,\"colorsRange\":[],\"invertColors\":false,\"percentageMode\":false,\"valueAxes\":[{\"show\":false,\"id\":\"ValueAxis-1\",\"type\":\"value\",\"scale\":{\"type\":\"linear\",\"defaultYExtents\":false},\"labels\":{\"show\":false,\"rotate\":0,\"overwriteColor\":false,\"color\":\"#555\"}}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"bytes\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"geo.src\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:e2023110-3dcb-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:32.135Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Rendering Test: guage",
+        "uiStateJSON": "{\"vis\":{\"colors\":{\"0 - 50000\":\"#EF843C\",\"75000 - 10000000\":\"#3F6833\"},\"defaultColors\":{\"0 - 5000000\":\"rgb(0,104,55)\",\"50000000 - 74998990099\":\"rgb(165,0,38)\"}}}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: guage\",\"type\":\"gauge\",\"params\":{\"addLegend\":true,\"addTooltip\":true,\"gauge\":{\"backStyle\":\"Full\",\"colorSchema\":\"Green to Red\",\"colorsRange\":[{\"from\":0,\"to\":5000000},{\"from\":50000000,\"to\":74998990099}],\"extendRange\":true,\"gaugeColorMode\":\"Labels\",\"gaugeStyle\":\"Full\",\"gaugeType\":\"Arc\",\"invertColors\":false,\"labels\":{\"color\":\"black\",\"show\":true},\"orientation\":\"vertical\",\"percentageMode\":false,\"scale\":{\"color\":\"#333\",\"labels\":false,\"show\":true},\"style\":{\"bgColor\":false,\"bgFill\":\"#eee\",\"bgMask\":false,\"bgWidth\":0.9,\"fontSize\":60,\"labelColor\":true,\"mask\":false,\"maskBars\":50,\"subText\":\"\",\"width\":0.9},\"type\":\"meter\",\"alignment\":\"horizontal\"},\"isDisplayWarning\":false,\"type\":\"gauge\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"machine.ram\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:b92ae920-3dcc-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:31.110Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Rendering Test: timelion",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: timelion\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(*, metric=avg:bytes, split=ip:5)\",\"interval\":\"auto\"},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:e4d8b430-3dcc-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:31.106Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Rendering Test: tsvb-guage",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: tsvb-guage\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"gauge\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"avg\",\"field\":\"bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"split_color_mode\":\"gradient\"},{\"id\":\"d18e5970-3dcc-11e8-a2f6-c162ca6cf6ea\",\"color\":\"rgba(160,70,216,1)\",\"split_mode\":\"filter\",\"metrics\":[{\"id\":\"d18e5971-3dcc-11e8-a2f6-c162ca6cf6ea\",\"type\":\"avg\",\"field\":\"bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"filter\":{\"query\":\"bytes:>1000\",\"language\":\"lucene\"},\"split_color_mode\":\"gradient\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"logstash-*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1,\"background_color_rules\":[{\"id\":\"c50bd5b0-3dcc-11e8-a2f6-c162ca6cf6ea\"}],\"bar_color_rules\":[{\"id\":\"cd25a820-3dcc-11e8-a2f6-c162ca6cf6ea\"}],\"gauge_color_rules\":[{\"id\":\"e0be22e0-3dcc-11e8-a2f6-c162ca6cf6ea\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"use_kibana_indexes\":false,\"hide_last_value_indicator\":true},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:4c0f47e0-3dcd-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:31.111Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Rendering Test: markdown",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: markdown\",\"type\":\"markdown\",\"params\":{\"fontSize\":20,\"openLinksInNewTab\":false,\"markdown\":\"I'm a markdown!\"},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:2d1b1620-3dcd-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "control_0_index_pattern",
+          "type": "index-pattern"
+        },
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "control_1_index_pattern",
+          "type": "index-pattern"
+        },
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "control_2_index_pattern",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:31.123Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Rendering Test: input control",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: input control\",\"type\":\"input_control_vis\",\"params\":{\"controls\":[{\"id\":\"1523481142694\",\"fieldName\":\"bytes\",\"parent\":\"\",\"label\":\"Bytes Input List\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_0_index_pattern\"},{\"id\":\"1523481163654\",\"fieldName\":\"bytes\",\"parent\":\"\",\"label\":\"Bytes range\",\"type\":\"range\",\"options\":{\"decimalPlaces\":0,\"step\":1},\"indexPatternRefName\":\"control_1_index_pattern\"},{\"id\":\"1523481176519\",\"fieldName\":\"sound.keyword\",\"parent\":\"\",\"label\":\"Animal sounds\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_2_index_pattern\"}],\"updateFiltersOnChange\":false,\"useTimeFilter\":false,\"pinFilters\":false},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:8bc8d6c0-3e6e-11e8-bbb9-e15942d5d48c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "f908c8e0-3e6d-11e8-bbb9-e15942d5d48c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "f908c8e0-3e6d-11e8-bbb9-e15942d5d48c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:31.173Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[{\"meta\":{\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"size.keyword\",\"value\":\"extra large\",\"params\":{\"query\":\"extra large\",\"type\":\"phrase\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"size.keyword\":{\"query\":\"extra large\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Rendering Test: non timebased line chart - dog data - with filter",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{\"field\":\"trainability\"},\"schema\":\"metric\",\"type\":\"max\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"field\":\"breed.keyword\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"size\":5},\"schema\":\"segment\",\"type\":\"terms\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"field\":\"barking level\"},\"schema\":\"metric\",\"type\":\"max\"},{\"enabled\":true,\"id\":\"4\",\"params\":{\"field\":\"activity level\"},\"schema\":\"metric\",\"type\":\"max\"}],\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{},\"type\":\"category\"}],\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"legendPosition\":\"right\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Max trainability\"},\"drawLinesBetweenPoints\":true,\"mode\":\"normal\",\"show\":\"true\",\"showCircles\":true,\"type\":\"line\",\"valueAxis\":\"ValueAxis-1\"},{\"data\":{\"id\":\"3\",\"label\":\"Max barking level\"},\"drawLinesBetweenPoints\":true,\"mode\":\"normal\",\"show\":true,\"showCircles\":true,\"type\":\"line\",\"valueAxis\":\"ValueAxis-1\"},{\"data\":{\"id\":\"4\",\"label\":\"Max activity level\"},\"drawLinesBetweenPoints\":true,\"mode\":\"normal\",\"show\":true,\"showCircles\":true,\"type\":\"line\",\"valueAxis\":\"ValueAxis-1\"}],\"times\":[],\"type\":\"line\",\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Max trainability\"},\"type\":\"value\"}],\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"fittingFunction\":\"zero\"},\"title\":\"Rendering Test: non timebased line chart - dog data - with filter\",\"type\":\"line\"}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:42535e30-3dcd-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "control_0_index_pattern",
+          "type": "index-pattern"
+        },
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "control_1_index_pattern",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:31.124Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Rendering Test: input control parent",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: input control parent\",\"type\":\"input_control_vis\",\"params\":{\"controls\":[{\"id\":\"1523481216736\",\"fieldName\":\"animal.keyword\",\"parent\":\"\",\"label\":\"Animal type\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_0_index_pattern\"},{\"id\":\"1523481176519\",\"fieldName\":\"sound.keyword\",\"parent\":\"1523481216736\",\"label\":\"Animal sounds\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_1_index_pattern\"}],\"updateFiltersOnChange\":false,\"useTimeFilter\":false,\"pinFilters\":false},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:7fda8ee0-3dcd-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:30.344Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Rendering Test: vega",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: vega\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n/*\\n\\nWelcome to Vega visualizations.  Here you can design your own dataviz from scratch using a declarative language called Vega, or its simpler form Vega-Lite.  In Vega, you have the full control of what data is loaded, even from multiple sources, how that data is transformed, and what visual elements are used to show it.  Use help icon to view Vega examples, tutorials, and other docs.  Use the wrench icon to reformat this text, or to remove comments.\\n\\nThis example graph shows the document count in all indexes in the current time range.  You might need to adjust the time filter in the upper right corner.\\n*/\\n\\n  $schema: https://vega.github.io/schema/vega-lite/v2.json\\n  title: Event counts from all indexes\\n\\n  // Define the data source\\n  data: {\\n    url: {\\n/*\\nAn object instead of a string for the \\\"url\\\" param is treated as an Elasticsearch query. Anything inside this object is not part of the Vega language, but only understood by Kibana and Elasticsearch server. This query counts the number of documents per time interval, assuming you have a @timestamp field in your data.\\n\\nKibana has a special handling for the fields surrounded by \\\"%\\\".  They are processed before the the query is sent to Elasticsearch. This way the query becomes context aware, and can use the time range and the dashboard filters.\\n*/\\n\\n      // Apply dashboard context filters when set\\n      %context%: true\\n      // Filter the time picker (upper right corner) with this field\\n      %timefield%: @timestamp\\n\\n/*\\nSee .search() documentation for :  https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#api-search\\n*/\\n\\n      // Which index to search\\n      index: _all\\n      // Aggregate data by the time field into time buckets, counting the number of documents in each bucket.\\n      body: {\\n        aggs: {\\n          time_buckets: {\\n            date_histogram: {\\n              // Use date histogram aggregation on @timestamp field\\n              field: @timestamp\\n              // The interval value will depend on the daterange picker (true), or use an integer to set an approximate bucket count\\n              interval: {%autointerval%: true}\\n              // Make sure we get an entire range, even if it has no data\\n              extended_bounds: {\\n                // Use the current time range's start and end\\n                min: {%timefilter%: \\\"min\\\"}\\n                max: {%timefilter%: \\\"max\\\"}\\n              }\\n              // Use this for linear (e.g. line, area) graphs.  Without it, empty buckets will not show up\\n              min_doc_count: 0\\n            }\\n          }\\n        }\\n        // Speed up the response by only including aggregation results\\n        size: 0\\n      }\\n    }\\n/*\\nElasticsearch will return results in this format:\\n\\naggregations: {\\n  time_buckets: {\\n    buckets: [\\n      {\\n        key_as_string: 2015-11-30T22:00:00.000Z\\n        key: 1448920800000\\n        doc_count: 0\\n      },\\n      {\\n        key_as_string: 2015-11-30T23:00:00.000Z\\n        key: 1448924400000\\n        doc_count: 0\\n      }\\n      ...\\n    ]\\n  }\\n}\\n\\nFor our graph, we only need the list of bucket values.  Use the format.property to discard everything else.\\n*/\\n    format: {property: \\\"aggregations.time_buckets.buckets\\\"}\\n  }\\n\\n  // \\\"mark\\\" is the graphics element used to show our data.  Other mark values are: area, bar, circle, line, point, rect, rule, square, text, and tick.  See https://vega.github.io/vega-lite/docs/mark.html\\n  mark: line\\n\\n  // \\\"encoding\\\" tells the \\\"mark\\\" what data to use and in what way.  See https://vega.github.io/vega-lite/docs/encoding.html\\n  encoding: {\\n    x: {\\n      // The \\\"key\\\" value is the timestamp in milliseconds.  Use it for X axis.\\n      field: key\\n      type: temporal\\n      axis: {title: false} // Customize X axis format\\n    }\\n    y: {\\n      // The \\\"doc_count\\\" is the count per bucket.  Use it for Y axis.\\n      field: doc_count\\n      type: quantitative\\n      axis: {title: \\\"Document count\\\"}\\n    }\\n  }\\n}\\n\"},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:02a2e4e0-3dcd-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:30.351Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Rendering Test: tsvb-table",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: tsvb-table\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"table\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"avg\",\"field\":\"bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"split_color_mode\":\"gradient\"},{\"id\":\"d18e5970-3dcc-11e8-a2f6-c162ca6cf6ea\",\"color\":\"rgba(160,70,216,1)\",\"split_mode\":\"filter\",\"metrics\":[{\"id\":\"d18e5971-3dcc-11e8-a2f6-c162ca6cf6ea\",\"type\":\"avg\",\"field\":\"bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"filter\":{\"query\":\"bytes:>1000\",\"language\":\"lucene\"},\"split_color_mode\":\"gradient\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"logstash-*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1,\"background_color_rules\":[{\"id\":\"c50bd5b0-3dcc-11e8-a2f6-c162ca6cf6ea\"}],\"bar_color_rules\":[{\"id\":\"cd25a820-3dcc-11e8-a2f6-c162ca6cf6ea\"}],\"gauge_color_rules\":[{\"id\":\"e0be22e0-3dcc-11e8-a2f6-c162ca6cf6ea\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"markdown\":\"\\nHi Avg last bytes: {{ average_of_bytes.last.raw }}\",\"pivot_id\":\"bytes\",\"pivot_label\":\"Hello\",\"use_kibana_indexes\":false,\"hide_last_value_indicator\":true},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:f81134a0-3dcc-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:30.355Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Rendering Test: tsvb-markdown",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: tsvb-markdown\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"markdown\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"avg\",\"field\":\"bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"split_color_mode\":\"gradient\"},{\"id\":\"d18e5970-3dcc-11e8-a2f6-c162ca6cf6ea\",\"color\":\"rgba(160,70,216,1)\",\"split_mode\":\"filter\",\"metrics\":[{\"id\":\"d18e5971-3dcc-11e8-a2f6-c162ca6cf6ea\",\"type\":\"avg\",\"field\":\"bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"filter\":{\"query\":\"bytes:>1000\",\"language\":\"lucene\"},\"split_color_mode\":\"gradient\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"logstash-*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1,\"background_color_rules\":[{\"id\":\"c50bd5b0-3dcc-11e8-a2f6-c162ca6cf6ea\"}],\"bar_color_rules\":[{\"id\":\"cd25a820-3dcc-11e8-a2f6-c162ca6cf6ea\"}],\"gauge_color_rules\":[{\"id\":\"e0be22e0-3dcc-11e8-a2f6-c162ca6cf6ea\"}],\"gauge_width\":10,\"gauge_inner_width\":10,\"gauge_style\":\"half\",\"markdown\":\"\\nHi Avg last bytes: {{ average_of_bytes.last.raw }}\",\"use_kibana_indexes\":false,\"hide_last_value_indicator\":true},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:df815d20-3dcc-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:30.349Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Rendering Test: tsvb-topn",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: tsvb-topn\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"top_n\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"avg\",\"field\":\"bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"split_color_mode\":\"gradient\"},{\"id\":\"d18e5970-3dcc-11e8-a2f6-c162ca6cf6ea\",\"color\":\"rgba(160,70,216,1)\",\"split_mode\":\"filter\",\"metrics\":[{\"id\":\"d18e5971-3dcc-11e8-a2f6-c162ca6cf6ea\",\"type\":\"avg\",\"field\":\"bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"filter\":{\"query\":\"bytes:>1000\",\"language\":\"lucene\"},\"split_color_mode\":\"gradient\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"logstash-*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1,\"background_color_rules\":[{\"id\":\"c50bd5b0-3dcc-11e8-a2f6-c162ca6cf6ea\"}],\"bar_color_rules\":[{\"id\":\"cd25a820-3dcc-11e8-a2f6-c162ca6cf6ea\"}],\"use_kibana_indexes\":false,\"hide_last_value_indicator\":true},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:cc43fab0-3dcc-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:30.353Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Rendering Test: tsvb-metric",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: tsvb-metric\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"metric\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"sum_of_squares\",\"field\":\"bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"split_color_mode\":\"gradient\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"logstash-*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1,\"background_color_rules\":[{\"id\":\"c50bd5b0-3dcc-11e8-a2f6-c162ca6cf6ea\"}],\"use_kibana_indexes\":false,\"hide_last_value_indicator\":true},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:c40f4d40-3dcc-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:30.347Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Rendering Test: tsvb-ts",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: tsvb-ts\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"timeseries\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"count\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"split_color_mode\":\"gradient\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1,\"use_kibana_indexes\":false},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:ffa2e0c0-3dcb-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:33.153Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Rendering Test: goal",
+        "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: goal\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"isDisplayWarning\":false,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":true,\"gaugeType\":\"Arc\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":4000}],\"invertColors\":false,\"labels\":{\"show\":true,\"color\":\"black\"},\"scale\":{\"show\":false,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"meter\",\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"geo.src\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":2,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:37a541c0-3dcc-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:33.156Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[{\"meta\":{\"negate\":true,\"disabled\":false,\"alias\":null,\"type\":\"range\",\"key\":\"bytes\",\"value\":\"0 to 10,000\",\"params\":{\"gte\":0,\"lt\":10000},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"range\":{\"bytes\":{\"gte\":0,\"lt\":10000}},\"$state\":{\"store\":\"appState\"}}],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Rendering Test: geo map",
+        "uiStateJSON": "{\"mapZoom\":4,\"mapCenter\":[35.460669951495305,-85.60546875000001]}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: geo map\",\"type\":\"tile_map\",\"params\":{\"mapType\":\"Scaled Circle Markers\",\"isDesaturated\":true,\"addTooltip\":true,\"heatClusterSize\":1.5,\"legendPosition\":\"bottomright\",\"mapZoom\":2,\"mapCenter\":[0,0],\"wms\":{\"enabled\":false,\"options\":{\"format\":\"image/png\",\"transparent\":true},\"baseLayersAreLoaded\":{},\"tmsLayers\":[{\"id\":\"road_map\",\"url\":\"https://tiles-stage.elastic.co/v2/default/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana&my_app_version=6.3.0\",\"minZoom\":0,\"maxZoom\":10,\"attribution\":\"<p>&#169; <a href=\\\"http://www.openstreetmap.org/copyright\\\">OpenStreetMap</a> contributors | <a href=\\\"https://www.elastic.co/elastic-maps-service\\\">Elastic Maps Service</a></p>&#10;\",\"subdomains\":[]}],\"selectedTmsLayer\":{\"id\":\"road_map\",\"url\":\"https://tiles-stage.elastic.co/v2/default/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana&my_app_version=6.3.0\",\"minZoom\":0,\"maxZoom\":10,\"attribution\":\"<p>&#169; <a href=\\\"http://www.openstreetmap.org/copyright\\\">OpenStreetMap</a> contributors | <a href=\\\"https://www.elastic.co/elastic-maps-service\\\">Elastic Maps Service</a></p>&#10;\",\"subdomains\":[]}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"geohash_grid\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.coordinates\",\"autoPrecision\":true,\"isFilteredByCollar\":true,\"useGeocentroid\":true,\"precision\":3}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:4b5d6ef0-3dcb-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:33.162Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Rendering Test: datatable",
+        "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: datatable\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\",\"showToolbar\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"clientip\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:3525b840-3dcb-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:33.163Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Rendering Test: bar",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: bar\",\"type\":\"horizontal_bar\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":200},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":75,\"filter\":true,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"normal\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"geo.src\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":3,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:e6140540-3dca-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:33.165Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[{\"meta\":{\"negate\":true,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"geo.src\",\"value\":\"CN\",\"params\":{\"query\":\"CN\",\"type\":\"phrase\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"geo.src\":{\"query\":\"CN\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Rendering Test: area with not filter",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: area with not filter\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"fittingFunction\":\"zero\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"group\",\"params\":{\"filters\":[{\"input\":{\"query\":\"bytes:>1000\",\"language\":\"lucene\"},\"label\":\"\"},{\"input\":{\"query\":\"bytes:>10\",\"language\":\"lucene\"}}]}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:4c0c3f90-3e5a-11e8-9fc3-39e49624228e",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:33.166Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[{\"meta\":{\"field\":\"isDog\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"isDog\",\"value\":\"true\",\"params\":{\"value\":true},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"script\":{\"script\":{\"inline\":\"boolean compare(Supplier s, def v) {return s.get() == v;}compare(() -> { return doc['animal.keyword'].value == 'dog' }, params.value);\",\"lang\":\"painless\",\"params\":{\"value\":true}}},\"$state\":{\"store\":\"appState\"}}],\"query\":{\"query\":\"weightLbs:>40\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Rendering Test: scripted filter and query",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: scripted filter and query\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"distinctColors\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"sound.keyword\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:50643b60-3dd3-11e8-b2b9-5d5dc1715159",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:34.195Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Rendering Test: animal sounds pie",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: animal sounds pie\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"distinctColors\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"sound.keyword\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:771b4f10-3e59-11e8-9fc3-39e49624228e",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "a16d1990-3dca-11e8-8660-4d65aa086b3c",
+          "name": "search_0",
+          "type": "search"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:34.200Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}"
+        },
+        "savedSearchRefName": "search_0",
+        "title": "Rendering Test: animal weights linked to search",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Rendering Test: animal weights linked to search\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"distinctColors\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"name.keyword\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:76c7f020-4194-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:34.583Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Filter Bytes Test: tsvb top n with bytes filter",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: tsvb top n with bytes filter\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"top_n\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"#68BC00\",\"split_mode\":\"filters\",\"metrics\":[{\"id\":\"482d6560-4194-11e8-a461-7d278185cba4\",\"type\":\"avg\",\"field\":\"bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"clientip\",\"filter\":{\"query\":\"Filter Bytes Test:>1000\",\"language\":\"lucene\"},\"override_index_pattern\":0,\"series_index_pattern\":\"logstash-*\",\"series_time_field\":\"utc_time\",\"series_interval\":\"1m\",\"value_template\":\"\",\"split_filters\":[{\"filter\":{\"query\":\"Filter Bytes Test:>100\",\"language\":\"lucene\"},\"label\":\"\",\"color\":\"#68BC00\",\"id\":\"39a107e0-4194-11e8-a461-7d278185cba4\"}],\"split_color_mode\":\"gradient\"},{\"id\":\"4fd5b150-4194-11e8-a461-7d278185cba4\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"4fd5b151-4194-11e8-a461-7d278185cba4\",\"type\":\"avg\",\"field\":\"bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"filter\":{\"query\":\"Filter Bytes Test:>3000\",\"language\":\"lucene\"},\"split_color_mode\":\"gradient\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"logstash-*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1,\"background_color_rules\":[{\"id\":\"06893260-4194-11e8-a461-7d278185cba4\"}],\"bar_color_rules\":[{\"id\":\"36a0e740-4194-11e8-a461-7d278185cba4\"}],\"use_kibana_indexes\":false,\"hide_last_value_indicator\":true},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:0ca8c600-4195-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "control_0_index_pattern",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:35.229Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Filter Bytes Test: input control with filter",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: input control with filter\",\"type\":\"input_control_vis\",\"params\":{\"controls\":[{\"id\":\"1523896850250\",\"fieldName\":\"bytes\",\"parent\":\"\",\"label\":\"Byte Options\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"size\":10,\"order\":\"desc\"},\"indexPatternRefName\":\"control_0_index_pattern\"}],\"updateFiltersOnChange\":false,\"useTimeFilter\":false,\"pinFilters\":false},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:039e4770-4194-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:35.220Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Filter Bytes Test: tsvb time series with bytes filter split by clientip",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: tsvb time series with bytes filter split by clientip\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"timeseries\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"value\":\"\",\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"sum\",\"field\":\"bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"clientip\",\"filter\":{\"query\":\"Filter Bytes Test:>1000\",\"language\":\"lucene\"},\"split_color_mode\":\"gradient\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"logstash-*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1,\"use_kibana_indexes\":false},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:760a9060-4190-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:35.235Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[{\"meta\":{\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"geo.src\",\"value\":\"US\",\"params\":{\"query\":\"US\",\"type\":\"phrase\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"geo.src\":{\"query\":\"US\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Filter Bytes Test: max bytes in US - area chart with filter",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: max bytes in US - area chart with filter\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Max bytes\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Max bytes\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"fittingFunction\":\"zero\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"bytes\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1,\"extended_bounds\":{}}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:b3e70d00-4190-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:35.236Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Filter Bytes Test: standard deviation heatmap with other bucket",
+        "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"-4,000 - 1,000\":\"rgb(247,252,245)\",\"1,000 - 6,000\":\"rgb(199,233,192)\",\"6,000 - 11,000\":\"rgb(116,196,118)\",\"11,000 - 16,000\":\"rgb(35,139,69)\"}}}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: standard deviation heatmap with other bucket\",\"type\":\"heatmap\",\"params\":{\"type\":\"heatmap\",\"addTooltip\":true,\"addLegend\":true,\"enableHover\":false,\"legendPosition\":\"right\",\"times\":[],\"colorsNumber\":4,\"colorSchema\":\"Greens\",\"setColorRange\":false,\"colorsRange\":[],\"invertColors\":false,\"percentageMode\":false,\"valueAxes\":[{\"show\":false,\"id\":\"ValueAxis-1\",\"type\":\"value\",\"scale\":{\"type\":\"linear\",\"defaultYExtents\":false},\"labels\":{\"show\":false,\"rotate\":0,\"overwriteColor\":false,\"color\":\"#555\"}}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"std_dev\",\"schema\":\"metric\",\"params\":{\"field\":\"bytes\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.src\",\"otherBucket\":true,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"_term\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:c10c6b00-4191-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:36.267Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Filter Bytes Test: max bytes guage percent mode",
+        "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 1\":\"rgb(0,104,55)\",\"1 - 15\":\"rgb(255,255,190)\",\"15 - 100\":\"rgb(165,0,38)\"}}}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: max bytes guage percent mode\",\"type\":\"gauge\",\"params\":{\"type\":\"gauge\",\"addTooltip\":true,\"addLegend\":true,\"isDisplayWarning\":false,\"gauge\":{\"extendRange\":true,\"percentageMode\":true,\"gaugeType\":\"Arc\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"Labels\",\"colorsRange\":[{\"from\":0,\"to\":500},{\"from\":500,\"to\":7500},{\"from\":7500,\"to\":50000}],\"invertColors\":false,\"labels\":{\"show\":true,\"color\":\"black\"},\"scale\":{\"show\":true,\"labels\":false,\"color\":\"#333\"},\"type\":\"meter\",\"style\":{\"bgWidth\":0.9,\"width\":0.9,\"mask\":false,\"bgMask\":false,\"maskBars\":50,\"bgFill\":\"#eee\",\"bgColor\":false,\"subText\":\"Im subtext\",\"fontSize\":60,\"labelColor\":true},\"alignment\":\"horizontal\"}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"bytes\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:03d2afd0-4192-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:36.269Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Filter Bytes Test: Goal unique count",
+        "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 10000\":\"rgb(0,104,55)\"}}}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: Goal unique count\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"isDisplayWarning\":false,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":false,\"gaugeType\":\"Arc\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"invertColors\":false,\"labels\":{\"show\":true,\"color\":\"black\"},\"scale\":{\"show\":false,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"meter\",\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"bytes\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:7ff2c4c0-4191-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:36.270Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Filter Bytes Test: Data table top hit with significant terms geo.src",
+        "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: Data table top hit with significant terms geo.src\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\",\"showToolbar\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"top_hits\",\"schema\":\"metric\",\"params\":{\"field\":\"bytes\",\"aggregate\":\"average\",\"size\":1,\"sortField\":\"@timestamp\",\"sortOrder\":\"desc\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"significant_terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"geo.src\",\"size\":10}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:df72ad40-4194-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:36.276Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[{\"meta\":{\"negate\":true,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"bytes\",\"value\":\"0\",\"params\":{\"query\":0,\"type\":\"phrase\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"bytes\":{\"query\":0,\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Filter Bytes Test: tag cloud with not 0 bytes filter",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: tag cloud with not 0 bytes filter\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"bytes\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:63983430-4192-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:06:36.275Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[{\"meta\":{\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"geo.src\",\"value\":\"US\",\"params\":{\"query\":\"US\",\"type\":\"phrase\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"geo.src\":{\"query\":\"US\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"query\":{\"query\":\"Filter Bytes Test:>5000\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Filter Bytes Test: geo map with filter and query bytes > 5000 in US geo.src, heatmap setting",
+        "uiStateJSON": "{\"mapZoom\":7,\"mapCenter\":[42.98857645832184,-75.49804687500001]}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: geo map with filter and query bytes > 5000 in US geo.src, heatmap setting\",\"type\":\"tile_map\",\"params\":{\"mapType\":\"Heatmap\",\"isDesaturated\":true,\"addTooltip\":true,\"heatClusterSize\":1.5,\"legendPosition\":\"bottomright\",\"mapZoom\":2,\"mapCenter\":[0,0],\"wms\":{\"enabled\":false,\"options\":{\"format\":\"image/png\",\"transparent\":true},\"baseLayersAreLoaded\":{},\"tmsLayers\":[{\"id\":\"road_map\",\"url\":\"https://tiles-stage.elastic.co/v2/default/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana&my_app_version=6.3.0\",\"minZoom\":0,\"maxZoom\":10,\"attribution\":\"<p>&#169; <a href=\\\"http://www.openstreetmap.org/copyright\\\">OpenStreetMap</a> contributors | <a href=\\\"https://www.elastic.co/elastic-maps-service\\\">Elastic Maps Service</a></p>&#10;\",\"subdomains\":[]}],\"selectedTmsLayer\":{\"id\":\"road_map\",\"url\":\"https://tiles-stage.elastic.co/v2/default/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana&my_app_version=6.3.0\",\"minZoom\":0,\"maxZoom\":10,\"attribution\":\"<p>&#169; <a href=\\\"http://www.openstreetmap.org/copyright\\\">OpenStreetMap</a> contributors | <a href=\\\"https://www.elastic.co/elastic-maps-service\\\">Elastic Maps Service</a></p>&#10;\",\"subdomains\":[]}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"geohash_grid\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.coordinates\",\"autoPrecision\":true,\"isFilteredByCollar\":true,\"useGeocentroid\":true,\"precision\":4}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "search:be5accf0-3dca-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "search": "7.9.3"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "search": {
+        "columns": [
+          "agent",
+          "bytes",
+          "clientip"
+        ],
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "sort": [
+          [
+            "@timestamp",
+            "desc"
+          ]
+        ],
+        "title": "Rendering Test: saved search",
+        "version": 1
+      },
+      "type": "search",
+      "updated_at": "2018-04-17T15:09:39.805Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "search:ca5ada40-3dca-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "search": "7.9.3"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        }
+      ],
+      "search": {
+        "columns": [
+          "agent",
+          "bytes",
+          "clientip"
+        ],
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[{\"meta\":{\"negate\":false,\"type\":\"phrase\",\"key\":\"bytes\",\"value\":\"1,607\",\"params\":{\"query\":1607,\"type\":\"phrase\"},\"disabled\":false,\"alias\":null,\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"bytes\":{\"query\":1607,\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "sort": [
+          [
+            "@timestamp",
+            "desc"
+          ]
+        ],
+        "title": "Filter Bytes Test: search with filter",
+        "version": 1
+      },
+      "type": "search",
+      "updated_at": "2018-04-17T15:09:55.976Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:9bebe980-4192-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:59:42.648Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Filter Bytes Test: timelion split 5 on bytes",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: timelion split 5 on bytes\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(*, split=bytes:5)\",\"interval\":\"auto\"},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:1dcdfe30-4192-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T15:59:56.976Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"bytes:>100\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Filter Bytes Test: min bytes metric with query",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: min bytes metric with query\",\"type\":\"metric\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"type\":\"metric\",\"metric\":{\"percentageMode\":false,\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"metricColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"labels\":{\"show\":true},\"invertColors\":false,\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"min\",\"schema\":\"metric\",\"params\":{\"field\":\"bytes\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:35417e50-4194-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T16:06:03.785Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Filter Bytes Test: tsvb metric with custom interval and bytes filter",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: tsvb metric with custom interval and bytes filter\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"metric\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"value\":\"\",\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"sum\",\"field\":\"bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"clientip\",\"filter\":{\"query\":\"Filter Bytes Test:>1000\",\"language\":\"lucene\"},\"override_index_pattern\":1,\"series_index_pattern\":\"logstash-*\",\"series_time_field\":\"utc_time\",\"series_interval\":\"1d\",\"value_template\":\"{{value}} custom template\",\"split_color_mode\":\"gradient\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"logstash-*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1,\"background_color_rules\":[{\"id\":\"06893260-4194-11e8-a461-7d278185cba4\"}],\"use_kibana_indexes\":false,\"hide_last_value_indicator\":true},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:9fb4c670-4194-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T16:32:59.086Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Filter Bytes Test: tsvb markdown",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: tsvb markdown\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"markdown\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"#68BC00\",\"split_mode\":\"filters\",\"metrics\":[{\"id\":\"482d6560-4194-11e8-a461-7d278185cba4\",\"type\":\"avg\",\"field\":\"bytes\"}],\"seperate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"terms_field\":\"clientip\",\"filter\":{\"query\":\"Filter Bytes Test:>1000\",\"language\":\"lucene\"},\"override_index_pattern\":0,\"series_index_pattern\":\"logstash-*\",\"series_time_field\":\"utc_time\",\"series_interval\":\"1m\",\"value_template\":\"\",\"split_filters\":[{\"filter\":{\"query\":\"bytes:>1000\",\"language\":\"lucene\"},\"label\":\"\",\"color\":\"#68BC00\",\"id\":\"39a107e0-4194-11e8-a461-7d278185cba4\"}],\"label\":\"\",\"var_name\":\"\",\"split_color_mode\":\"gradient\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"logstash-*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"show_legend\":1,\"show_grid\":1,\"background_color_rules\":[{\"id\":\"06893260-4194-11e8-a461-7d278185cba4\"}],\"bar_color_rules\":[{\"id\":\"36a0e740-4194-11e8-a461-7d278185cba4\"}],\"markdown\":\"{{bytes_1000.last.formatted}}\",\"use_kibana_indexes\":false,\"hide_last_value_indicator\":true},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:befdb6b0-3e59-11e8-9fc3-39e49624228e",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "a16d1990-3dca-11e8-8660-4d65aa086b3c",
+          "name": "search_0",
+          "type": "search"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T17:16:27.743Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[{\"meta\":{\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"animal.keyword\",\"value\":\"dog\",\"params\":{\"query\":\"dog\",\"type\":\"phrase\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"animal.keyword\":{\"query\":\"dog\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"query\":{\"language\":\"lucene\",\"query\":\"\"}}"
+        },
+        "savedSearchRefName": "search_0",
+        "title": "Filter Test: animals: linked to search with filter",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Test: animals: linked to search with filter\",\"type\":\"pie\",\"params\":{\"addLegend\":true,\"addTooltip\":true,\"isDonut\":true,\"labels\":{\"last_level\":true,\"show\":false,\"truncate\":100,\"values\":true},\"legendPosition\":\"right\",\"type\":\"pie\",\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"distinctColors\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"name.keyword\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:584c0300-4191-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T18:36:30.315Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"bytes:>9000\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Filter Bytes Test: split by geo with query",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: split by geo with query\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"distinctColors\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"sum\",\"schema\":\"metric\",\"params\":{\"field\":\"bytes\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.src\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "config:7.0.0-alpha1",
+    "index": ".kibana",
+    "source": {
+      "config": {
+        "buildNum": null,
+        "dateFormat:tz": "UTC",
+        "defaultIndex": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+        "notifications:lifetime:banner": 3600000,
+        "notifications:lifetime:error": 3600000,
+        "notifications:lifetime:info": 3600000,
+        "notifications:lifetime:warning": 3600000
+      },
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "config": "7.13.0"
+      },
+      "references": [
+      ],
+      "type": "config",
+      "updated_at": "2018-04-17T19:25:03.632Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:8090dcb0-4195-11e8-bb13-d53698fb349a",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
+      "type": "visualization",
+      "updated_at": "2018-04-17T19:28:21.967Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{}"
+        },
+        "title": "Filter Bytes Test: vega",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Filter Bytes Test: vega\",\"type\":\"vega\",\"params\":{\"spec\":\"{ \\nconfig: { kibana: { renderer: \\\"svg\\\" }},\\n/*\\n\\nWelcome to Vega visualizations.  Here you can design your own dataviz from scratch using a declarative language called Vega, or its simpler form Vega-Lite.  In Vega, you have the full control of what data is loaded, even from multiple sources, how that data is transformed, and what visual elements are used to show it.  Use help icon to view Vega examples, tutorials, and other docs.  Use the wrench icon to reformat this text, or to remove comments.\\n\\nThis example graph shows the document count in all indexes in the current time range.  You might need to adjust the time filter in the upper right corner.\\n*/\\n\\n  $schema: https://vega.github.io/schema/vega-lite/v2.json\\n  title: Event counts from all indexes\\n\\n  // Define the data source\\n  data: {\\n    url: {\\n/*\\nAn object instead of a string for the \\\"url\\\" param is treated as an Elasticsearch query. Anything inside this object is not part of the Vega language, but only understood by Kibana and Elasticsearch server. This query counts the number of documents per time interval, assuming you have a @timestamp field in your data.\\n\\nKibana has a special handling for the fields surrounded by \\\"%\\\".  They are processed before the the query is sent to Elasticsearch. This way the query becomes context aware, and can use the time range and the dashboard filters.\\n*/\\n\\n      // Apply dashboard context filters when set\\n      %context%: true\\n      // Filter the time picker (upper right corner) with this field\\n      %timefield%: @timestamp\\n\\n/*\\nSee .search() documentation for :  https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#api-search\\n*/\\n\\n      // Which index to search\\n      index: _all\\n      // Aggregate data by the time field into time buckets, counting the number of documents in each bucket.\\n      body: {\\n        aggs: {\\n          time_buckets: {\\n            date_histogram: {\\n              // Use date histogram aggregation on @timestamp field\\n              field: @timestamp\\n              // The interval value will depend on the daterange picker (true), or use an integer to set an approximate bucket count\\n              interval: {%autointerval%: true}\\n              // Make sure we get an entire range, even if it has no data\\n              extended_bounds: {\\n                // Use the current time range's start and end\\n                min: {%timefilter%: \\\"min\\\"}\\n                max: {%timefilter%: \\\"max\\\"}\\n              }\\n              // Use this for linear (e.g. line, area) graphs.  Without it, empty buckets will not show up\\n              min_doc_count: 0\\n            }\\n          }\\n        }\\n        // Speed up the response by only including aggregation results\\n        size: 0\\n      }\\n    }\\n/*\\nElasticsearch will return results in this format:\\n\\naggregations: {\\n  time_buckets: {\\n    buckets: [\\n      {\\n        key_as_string: 2015-11-30T22:00:00.000Z\\n        key: 1448920800000\\n        doc_count: 0\\n      },\\n      {\\n        key_as_string: 2015-11-30T23:00:00.000Z\\n        key: 1448924400000\\n        doc_count: 0\\n      }\\n      ...\\n    ]\\n  }\\n}\\n\\nFor our graph, we only need the list of bucket values.  Use the format.property to discard everything else.\\n*/\\n    format: {property: \\\"aggregations.time_buckets.buckets\\\"}\\n  }\\n\\n  // \\\"mark\\\" is the graphics element used to show our data.  Other mark values are: area, bar, circle, line, point, rect, rule, square, text, and tick.  See https://vega.github.io/vega-lite/docs/mark.html\\n  mark: line\\n\\n  // \\\"encoding\\\" tells the \\\"mark\\\" what data to use and in what way.  See https://vega.github.io/vega-lite/docs/encoding.html\\n  encoding: {\\n    x: {\\n      // The \\\"key\\\" value is the timestamp in milliseconds.  Use it for X axis.\\n      field: key\\n      type: temporal\\n      axis: {title: false} // Customize X axis format\\n    }\\n    y: {\\n      // The \\\"doc_count\\\" is the count per bucket.  Use it for Y axis.\\n      field: doc_count\\n      type: quantitative\\n      axis: {title: \\\"Document count\\\"}\\n    }\\n  }\\n}\\n\"},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "config:6.2.4",
+    "index": ".kibana",
+    "source": {
+      "config": {
+        "buildNum": 16627,
+        "defaultIndex": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+        "xPackMonitoring:showBanner": false
+      },
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "config": "7.13.0"
+      },
+      "references": [
+      ],
+      "type": "config",
+      "updated_at": "2018-05-09T20:50:57.021Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:edb65990-53ca-11e8-b481-c9426d020fcd",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-05-09T20:52:47.144Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "table created in 6_2",
+        "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}",
+        "version": 1,
+        "visState": "{\"title\":\"table created in 6_2\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMeticsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\",\"showToolbar\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"weightLbs\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"animal.keyword\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:0644f890-53cb-11e8-b481-c9426d020fcd",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2018-05-09T20:53:28.345Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"weightLbs:>10\",\"language\":\"lucene\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "Weight in lbs pie created in 6.2",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"Weight in lbs pie created in 6.2\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"distinctColors\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"weightLbs\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:1b2f47b0-53cb-11e8-b481-c9426d020fcd",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"weightLbs:>15\"},\"filter\":[{\"meta\":{\"field\":\"isDog\",\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"isDog\",\"value\":\"true\",\"params\":{\"value\":true},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"script\":{\"script\":{\"inline\":\"boolean compare(Supplier s, def v) {return s.get() == v;}compare(() -> { return doc['animal.keyword'].value == 'dog' }, params.value);\",\"lang\":\"painless\",\"params\":{\"value\":true}}},\"$state\":{\"store\":\"appState\"}}],\"highlightAll\":true,\"version\":true}"
+        },
+        "optionsJSON": "{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}",
+        "panelsJSON": "[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"w\":24,\"h\":12,\"x\":24,\"y\":0,\"i\":\"4\"},\"panelIndex\":\"4\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"w\":24,\"h\":12,\"x\":0,\"y\":0,\"i\":\"5\"},\"panelIndex\":\"5\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5\"}]",
+        "refreshInterval": {
+          "display": "Off",
+          "pause": false,
+          "value": 0
+        },
+        "timeFrom": "Mon Apr 09 2018 17:56:08 GMT-0400",
+        "timeRestore": true,
+        "timeTo": "Wed Apr 11 2018 17:56:08 GMT-0400",
+        "title": "Animal Weights (created in 6.2)",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "edb65990-53ca-11e8-b481-c9426d020fcd",
+          "name": "4:panel_4",
+          "type": "visualization"
+        },
+        {
+          "id": "0644f890-53cb-11e8-b481-c9426d020fcd",
+          "name": "5:panel_5",
+          "type": "visualization"
+        }
+      ],
+      "type": "dashboard",
+      "updated_at": "2018-05-09T20:54:03.435Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "index-pattern:a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "index-pattern": {
+        "fieldFormatMap": "{\"weightLbs\":{\"id\":\"number\",\"params\":{\"pattern\":\"0,0.0\"}},\"is_dog\":{\"id\":\"boolean\"},\"isDog\":{\"id\":\"boolean\"}}",
+        "fields": "[{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"animal\",\"type\":\"string\",\"count\":3,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"animal.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"name\",\"type\":\"string\",\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"name.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"sound\",\"type\":\"string\",\"count\":2,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"sound.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"weightLbs\",\"type\":\"number\",\"count\":2,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"isDog\",\"type\":\"boolean\",\"count\":0,\"scripted\":true,\"script\":\"return doc['animal.keyword'].value == 'dog'\",\"lang\":\"painless\",\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false}]",
+        "timeFieldName": "@timestamp",
+        "title": "animals-*"
+      },
+      "migrationVersion": {
+        "index-pattern": "7.11.0"
+      },
+      "references": [
+      ],
+      "type": "index-pattern",
+      "updated_at": "2018-05-09T20:55:44.314Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "search:6351c590-53cb-11e8-b481-c9426d020fcd",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "search": "7.9.3"
+      },
+      "references": [
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        }
+      ],
+      "search": {
+        "columns": [
+          "animal",
+          "sound",
+          "weightLbs"
+        ],
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"lucene\",\"query\":\"weightLbs:>10\"},\"filter\":[{\"meta\":{\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"sound.keyword\",\"value\":\"growl\",\"params\":{\"query\":\"growl\",\"type\":\"phrase\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"sound.keyword\":{\"query\":\"growl\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "sort": [
+          [
+            "@timestamp",
+            "desc"
+          ]
+        ],
+        "title": "Search created in 6.2",
+        "version": 1
+      },
+      "type": "search",
+      "updated_at": "2018-05-09T20:56:04.457Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "visualization:47b5cf60-9e93-11ea-853e-adc0effaf76d",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "1b1789d0-9e93-11ea-853e-adc0effaf76d",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
+      "type": "visualization",
+      "updated_at": "2020-05-25T15:16:27.743Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
+        },
+        "title": "vis with missing index pattern",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"type\":\"pie\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}],\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"distinctColors\":true},\"title\":\"vis with missing index pattern\"}"
+      }
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:502e63a0-9e93-11ea-853e-adc0effaf76d",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"
+        },
+        "optionsJSON": "{\"hidePanelTitles\":false,\"useMargins\":true}",
+        "panelsJSON": "[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"6cfbe6cc-1872-4cb4-9455-a02eeb75127e\"},\"panelIndex\":\"6cfbe6cc-1872-4cb4-9455-a02eeb75127e\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6cfbe6cc-1872-4cb4-9455-a02eeb75127e\"}]",
+        "timeRestore": false,
+        "title": "dashboard with missing index pattern",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "47b5cf60-9e93-11ea-853e-adc0effaf76d",
+          "name": "6cfbe6cc-1872-4cb4-9455-a02eeb75127e:panel_6cfbe6cc-1872-4cb4-9455-a02eeb75127e",
+          "type": "visualization"
+        }
+      ],
+      "type": "dashboard",
+      "updated_at": "2020-05-25T15:16:27.743Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "dashboard:6eb8a840-a32e-11ea-88c2-d56dd2b14bd7",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "dashboard": {
+        "description": "",
+        "hits": 0,
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\n  \"query\": {\n    \"language\": \"kuery\",\n    \"query\": \"\"\n  },\n  \"filter\": [\n    {\n      \"meta\": {\n        \"alias\": null,\n        \"negate\": false,\n        \"disabled\": true,\n        \"type\": \"phrase\",\n        \"key\": \"name\",\n        \"params\": {\n          \"query\": \"moo\"\n        },\n        \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"\n      },\n      \"query\": {\n        \"match_phrase\": {\n          \"name\": \"moo\"\n        }\n      },\n      \"$state\": {\n        \"store\": \"appState\"\n      }\n    },\n    {\n      \"meta\": {\n        \"alias\": null,\n        \"negate\": false,\n        \"disabled\": true,\n        \"type\": \"phrase\",\n        \"key\": \"baad-field\",\n        \"params\": {\n          \"query\": \"moo\"\n        },\n        \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index\"\n      },\n      \"query\": {\n        \"match_phrase\": {\n          \"baad-field\": \"moo\"\n        }\n      },\n      \"$state\": {\n        \"store\": \"appState\"\n      }\n    },\n    {\n      \"meta\": {\n        \"alias\": null,\n        \"negate\": false,\n        \"disabled\": false,\n        \"type\": \"phrase\",\n        \"key\": \"@timestamp\",\n        \"params\": {\n          \"query\": \"123\"\n        },\n        \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.filter[2].meta.index\"\n      },\n      \"query\": {\n        \"match_phrase\": {\n          \"@timestamp\": \"123\"\n        }\n      },\n      \"$state\": {\n        \"store\": \"appState\"\n      }\n    },\n    {\n      \"meta\": {\n        \"alias\": null,\n        \"negate\": false,\n        \"disabled\": false,\n        \"type\": \"exists\",\n        \"key\": \"extension\",\n        \"value\": \"exists\",\n        \"indexRefName\": \"kibanaSavedObjectMeta.searchSourceJSON.filter[3].meta.index\"\n      },\n      \"exists\": {\n        \"field\": \"extension\"\n      },\n      \"$state\": {\n        \"store\": \"appState\"\n      }\n    },\n    {\n      \"meta\": {\n        \"alias\": null,\n        \"negate\": false,\n        \"disabled\": false,\n        \"type\": \"phrase\",\n        \"key\": \"banana\",\n        \"params\": {\n          \"query\": \"yellow\"\n        }\n      },\n      \"query\": {\n        \"match_phrase\": {\n          \"banana\": \"yellow\"\n        }\n      },\n      \"$state\": {\n        \"store\": \"appState\"\n      }\n    }\n  ]\n}"
+        },
+        "optionsJSON": "{\n  \"hidePanelTitles\": false,\n  \"useMargins\": true\n}",
+        "panelsJSON": "[{\"version\":\"8.0.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"94a3dc1d-508a-4d42-a480-65b158925ba0\"},\"panelIndex\":\"94a3dc1d-508a-4d42-a480-65b158925ba0\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_94a3dc1d-508a-4d42-a480-65b158925ba0\"}]",
+        "refreshInterval": {
+          "pause": true,
+          "value": 0
+        },
+        "timeFrom": "now-10y",
+        "timeRestore": true,
+        "timeTo": "now",
+        "title": "dashboard with bad filters",
+        "version": 1
+      },
+      "migrationVersion": {
+        "dashboard": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-bad-index",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[1].meta.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[2].meta.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[3].meta.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "a0f483a0-3dc9-11e8-8660-4d65aa086b3c",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[4].meta.index",
+          "type": "index-pattern"
+        },
+        {
+          "id": "50643b60-3dd3-11e8-b2b9-5d5dc1715159",
+          "name": "94a3dc1d-508a-4d42-a480-65b158925ba0:panel_94a3dc1d-508a-4d42-a480-65b158925ba0",
+          "type": "visualization"
+        }
+      ],
+      "type": "dashboard",
+      "updated_at": "2020-06-04T09:26:04.272Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "config:8.0.0",
+    "index": ".kibana",
+    "source": {
+      "config": {
+        "accessibility:disableAnimations": true,
+        "buildNum": null,
+        "dateFormat:tz": "UTC",
+        "defaultIndex": "0bf35f60-3dc9-11e8-8660-4d65aa086b3c"
+      },
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "config": "7.13.0"
+      },
+      "references": [
+      ],
+      "type": "config",
+      "updated_at": "2020-06-04T09:22:54.572Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "ui-metric:DashboardPanelVersionInUrl:8.0.0",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
+      "type": "ui-metric",
+      "ui-metric": {
+        "count": 15
+      },
+      "updated_at": "2020-06-04T09:28:06.848Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "ui-metric:kibana-user_agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36",
+    "index": ".kibana",
+    "source": {
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
+      "type": "ui-metric",
+      "ui-metric": {
+        "count": 1
+      },
+      "updated_at": "2020-06-04T09:28:06.848Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "application_usage_daily:dashboards:2020-05-31",
+    "index": ".kibana",
+    "source": {
+      "application_usage_daily": {
+        "appId": "dashboards",
+        "minutesOnScreen": 13.956333333333333,
+        "numberOfClicks": 134,
+        "timestamp": "2020-05-31T00:00:00.000Z"
+      },
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
+      "type": "application_usage_daily",
+      "updated_at": "2021-06-10T22:39:09.215Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "application_usage_daily:home:2020-05-31",
+    "index": ".kibana",
+    "source": {
+      "application_usage_daily": {
+        "appId": "home",
+        "minutesOnScreen": 0.5708666666666666,
+        "numberOfClicks": 1,
+        "timestamp": "2020-05-31T00:00:00.000Z"
+      },
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
+      "type": "application_usage_daily",
+      "updated_at": "2021-06-10T22:39:09.215Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "application_usage_daily:management:2020-05-31",
+    "index": ".kibana",
+    "source": {
+      "application_usage_daily": {
+        "appId": "management",
+        "minutesOnScreen": 5.842616666666666,
+        "numberOfClicks": 107,
+        "timestamp": "2020-05-31T00:00:00.000Z"
+      },
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
+      "type": "application_usage_daily",
+      "updated_at": "2021-06-10T22:39:09.215Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "application_usage_daily:management:2020-06-04",
+    "index": ".kibana",
+    "source": {
+      "application_usage_daily": {
+        "appId": "management",
+        "minutesOnScreen": 2.5120666666666667,
+        "numberOfClicks": 38,
+        "timestamp": "2020-06-04T00:00:00.000Z"
+      },
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
+      "type": "application_usage_daily",
+      "updated_at": "2021-06-10T22:39:09.215Z"
+    },
+    "type": "_doc"
+  }
+}
+
+{
+  "type": "doc",
+  "value": {
+    "id": "application_usage_daily:dashboards:2020-06-04",
+    "index": ".kibana",
+    "source": {
+      "application_usage_daily": {
+        "appId": "dashboards",
+        "minutesOnScreen": 9.065083333333334,
+        "numberOfClicks": 21,
+        "timestamp": "2020-06-04T00:00:00.000Z"
+      },
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
+      "type": "application_usage_daily",
+      "updated_at": "2021-06-10T22:39:09.215Z"
+    },
+    "type": "_doc"
+  }
+}
\ No newline at end of file
diff --git a/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json.gz b/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json.gz
deleted file mode 100644
index ae78761fef0d3..0000000000000
Binary files a/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json.gz and /dev/null differ
diff --git a/test/functional/fixtures/es_archiver/dashboard/current/kibana/mappings.json b/test/functional/fixtures/es_archiver/dashboard/current/kibana/mappings.json
index 9f5edaad0fe76..b6e225951c545 100644
--- a/test/functional/fixtures/es_archiver/dashboard/current/kibana/mappings.json
+++ b/test/functional/fixtures/es_archiver/dashboard/current/kibana/mappings.json
@@ -2,155 +2,139 @@
   "type": "index",
   "value": {
     "aliases": {
-      ".kibana": {
-      }
+      ".kibana_$KIBANA_PACKAGE_VERSION": {},
+      ".kibana": {}
     },
-    "index": ".kibana_1",
+    "index": ".kibana_$KIBANA_PACKAGE_VERSION_001",
     "mappings": {
       "_meta": {
         "migrationMappingPropertyHashes": {
-          "application_usage_totals": "c897e4310c5f24b07caaff3db53ae2c1",
-          "application_usage_transactional": "965839e75f809fefe04f92dc4d99722a",
-          "config": "ae24d22d5986d04124cc6568f771066f",
-          "dashboard": "d00f614b29a80360e1190193fd333bab",
-          "index-pattern": "66eccb05066c5a89924f48a9e9736499",
+          "application_usage_daily": "43b8830d5d0df85a6823d290885fc9fd",
+          "application_usage_totals": "3d1b76c39bfb2cc8296b024d73854724",
+          "application_usage_transactional": "3d1b76c39bfb2cc8296b024d73854724",
+          "config": "c63748b75f39d0c54de12d12c1ccbc20",
+          "core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724",
+          "coreMigrationVersion": "2f4316de49999235636386fe51dc06c1",
+          "dashboard": "40554caf09725935e2c02e02563a2d07",
+          "index-pattern": "45915a1ad866812242df474eb0479052",
           "kql-telemetry": "d12a98a6f19a2d273696597547e064ee",
+          "legacy-url-alias": "6155300fd11a00e23d5cbaa39f0fce0a",
           "migrationVersion": "4a1746014a75ade3a714e1db5763276f",
           "namespace": "2f4316de49999235636386fe51dc06c1",
           "namespaces": "2f4316de49999235636386fe51dc06c1",
+          "originId": "2f4316de49999235636386fe51dc06c1",
           "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9",
           "references": "7997cf5a56cc02bdc9c93361bde732b0",
           "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4",
-          "search": "181661168bbadd1eff5902361e2a0d5c",
+          "search": "db2c00e39b36f40930a3b9fc71c823e1",
+          "search-telemetry": "3d1b76c39bfb2cc8296b024d73854724",
           "telemetry": "36a616f7026dfa617d6655df850fe16d",
           "timelion-sheet": "9a2a2748877c7a7b582fef201ab1d4cf",
-          "tsvb-validation-telemetry": "3a37ef6c8700ae6fc97d5c7da00e9215",
           "type": "2f4316de49999235636386fe51dc06c1",
+          "ui-counter": "0d409297dc5ebe1e3a1da691c6ee32e3",
           "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3",
           "updated_at": "00da57df13e94e9d98437d13ace4bfe0",
-          "url": "b675c3be8d76ecf029294d51dc7ec65d",
-          "visualization": "52d7a13ad68a150c4525b292d23e12cc"
+          "url": "c7f66a0df8b1b52f17c28c4adb111105",
+          "usage-counters": "8cc260bdceffec4ffc3ad165c97dc1b4",
+          "visualization": "f819cf6636b75c9e76ba733a0c6ef355"
         }
       },
       "dynamic": "strict",
       "properties": {
-        "application_usage_totals": {
+        "application_usage_daily": {
+          "dynamic": "false",
           "properties": {
-            "appId": {
-              "type": "keyword"
-            },
-            "minutesOnScreen": {
-              "type": "float"
-            },
-            "numberOfClicks": {
-              "type": "long"
-            }
-          }
-        },
-        "application_usage_transactional": {
-          "properties": {
-            "appId": {
-              "type": "keyword"
-            },
-            "minutesOnScreen": {
-              "type": "float"
-            },
-            "numberOfClicks": {
-              "type": "long"
-            },
             "timestamp": {
               "type": "date"
             }
           }
         },
+        "application_usage_totals": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "application_usage_transactional": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "config": {
-          "dynamic": "true",
+          "dynamic": "false",
           "properties": {
-            "accessibility:disableAnimations": {
-              "type": "boolean"
-            },
             "buildNum": {
               "type": "keyword"
-            },
-            "dateFormat:tz": {
-              "fields": {
-                "keyword": {
-                  "ignore_above": 256,
-                  "type": "keyword"
-                }
-              },
-              "type": "text"
-            },
-            "defaultIndex": {
-              "fields": {
-                "keyword": {
-                  "ignore_above": 256,
-                  "type": "keyword"
-                }
-              },
-              "type": "text"
-            },
-            "notifications:lifetime:banner": {
-              "type": "long"
-            },
-            "notifications:lifetime:error": {
-              "type": "long"
-            },
-            "notifications:lifetime:info": {
-              "type": "long"
-            },
-            "notifications:lifetime:warning": {
-              "type": "long"
-            },
-            "xPackMonitoring:showBanner": {
-              "type": "boolean"
             }
           }
         },
+        "core-usage-stats": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "coreMigrationVersion": {
+          "type": "keyword"
+        },
         "dashboard": {
           "properties": {
             "description": {
               "type": "text"
             },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "optionsJSON": {
+              "index": false,
               "type": "text"
             },
             "panelsJSON": {
+              "index": false,
               "type": "text"
             },
             "refreshInterval": {
               "properties": {
                 "display": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "keyword"
                 },
                 "pause": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "boolean"
                 },
                 "section": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 },
                 "value": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 }
               }
             },
             "timeFrom": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "timeRestore": {
+              "doc_values": false,
+              "index": false,
               "type": "boolean"
             },
             "timeTo": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
@@ -162,33 +146,13 @@
           }
         },
         "index-pattern": {
+          "dynamic": "false",
           "properties": {
-            "fieldFormatMap": {
-              "type": "text"
-            },
-            "fields": {
-              "type": "text"
-            },
-            "intervalName": {
-              "type": "keyword"
-            },
-            "notExpandable": {
-              "type": "boolean"
-            },
-            "sourceFilters": {
-              "type": "text"
-            },
-            "timeFieldName": {
-              "type": "keyword"
-            },
             "title": {
               "type": "text"
             },
             "type": {
               "type": "keyword"
-            },
-            "typeMeta": {
-              "type": "keyword"
             }
           }
         },
@@ -202,9 +166,32 @@
             }
           }
         },
+        "legacy-url-alias": {
+          "dynamic": "false",
+          "properties": {
+            "disabled": {
+              "type": "boolean"
+            },
+            "sourceId": {
+              "type": "keyword"
+            },
+            "targetType": {
+              "type": "keyword"
+            }
+          }
+        },
         "migrationVersion": {
           "dynamic": "true",
           "properties": {
+            "config": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            },
             "dashboard": {
               "fields": {
                 "keyword": {
@@ -249,6 +236,9 @@
         "namespaces": {
           "type": "keyword"
         },
+        "originId": {
+          "type": "keyword"
+        },
         "query": {
           "properties": {
             "description": {
@@ -305,22 +295,38 @@
         "search": {
           "properties": {
             "columns": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "description": {
               "type": "text"
             },
+            "grid": {
+              "enabled": false,
+              "type": "object"
+            },
+            "hideChart": {
+              "doc_values": false,
+              "index": false,
+              "type": "boolean"
+            },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "sort": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
@@ -331,12 +337,13 @@
             }
           }
         },
+        "search-telemetry": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "server": {
-          "properties": {
-            "uuid": {
-              "type": "keyword"
-            }
-          }
+          "dynamic": "false",
+          "type": "object"
         },
         "telemetry": {
           "properties": {
@@ -408,15 +415,19 @@
           }
         },
         "tsvb-validation-telemetry": {
-          "properties": {
-            "failedRequests": {
-              "type": "long"
-            }
-          }
+          "dynamic": "false",
+          "type": "object"
         },
         "type": {
           "type": "keyword"
         },
+        "ui-counter": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
         "ui-metric": {
           "properties": {
             "count": {
@@ -441,6 +452,7 @@
             "url": {
               "fields": {
                 "keyword": {
+                  "ignore_above": 2048,
                   "type": "keyword"
                 }
               },
@@ -448,6 +460,14 @@
             }
           }
         },
+        "usage-counters": {
+          "dynamic": "false",
+          "properties": {
+            "domainId": {
+              "type": "keyword"
+            }
+          }
+        },
         "visualization": {
           "properties": {
             "description": {
@@ -456,23 +476,28 @@
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "savedSearchRefName": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
             "uiStateJSON": {
+              "index": false,
               "type": "text"
             },
             "version": {
               "type": "integer"
             },
             "visState": {
+              "index": false,
               "type": "text"
             }
           }
@@ -483,7 +508,10 @@
       "index": {
         "auto_expand_replicas": "0-1",
         "number_of_replicas": "0",
-        "number_of_shards": "1"
+        "number_of_shards": "1",
+        "priority": "10",
+        "refresh_interval": "1s",
+        "routing_partition_size": "1"
       }
     }
   }
diff --git a/test/functional/fixtures/es_archiver/deprecations_service/data.json b/test/functional/fixtures/es_archiver/deprecations_service/data.json
index 31ce5af20b46c..1c36f2e177fc5 100644
--- a/test/functional/fixtures/es_archiver/deprecations_service/data.json
+++ b/test/functional/fixtures/es_archiver/deprecations_service/data.json
@@ -1,14 +1,18 @@
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
     "id": "test-deprecations-plugin:ff3733a0-9fty-11e7-ahb3-3dcb94193fab",
+    "index": ".kibana",
     "source": {
-      "type": "test-deprecations-plugin",
-      "updated_at": "2021-02-11T18:51:23.794Z",
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
       "test-deprecations-plugin": {
         "title": "Test saved object"
-      }
-    }
+      },
+      "type": "test-deprecations-plugin",
+      "updated_at": "2021-02-11T18:51:23.794Z"
+    },
+    "type": "_doc"
   }
-}
+}
\ No newline at end of file
diff --git a/test/functional/fixtures/es_archiver/deprecations_service/mappings.json b/test/functional/fixtures/es_archiver/deprecations_service/mappings.json
index 41cddecef0c41..5159b946e082f 100644
--- a/test/functional/fixtures/es_archiver/deprecations_service/mappings.json
+++ b/test/functional/fixtures/es_archiver/deprecations_service/mappings.json
@@ -2,132 +2,285 @@
   "type": "index",
   "value": {
     "aliases": {
+      ".kibana_$KIBANA_PACKAGE_VERSION": {},
       ".kibana": {}
     },
-    "index": ".kibana_1",
+    "index": ".kibana_$KIBANA_PACKAGE_VERSION_001",
     "mappings": {
+      "_meta": {
+        "migrationMappingPropertyHashes": {
+          "application_usage_daily": "43b8830d5d0df85a6823d290885fc9fd",
+          "application_usage_totals": "3d1b76c39bfb2cc8296b024d73854724",
+          "application_usage_transactional": "3d1b76c39bfb2cc8296b024d73854724",
+          "config": "c63748b75f39d0c54de12d12c1ccbc20",
+          "core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724",
+          "coreMigrationVersion": "2f4316de49999235636386fe51dc06c1",
+          "dashboard": "40554caf09725935e2c02e02563a2d07",
+          "index-pattern": "45915a1ad866812242df474eb0479052",
+          "kql-telemetry": "d12a98a6f19a2d273696597547e064ee",
+          "legacy-url-alias": "6155300fd11a00e23d5cbaa39f0fce0a",
+          "migrationVersion": "4a1746014a75ade3a714e1db5763276f",
+          "namespace": "2f4316de49999235636386fe51dc06c1",
+          "namespaces": "2f4316de49999235636386fe51dc06c1",
+          "originId": "2f4316de49999235636386fe51dc06c1",
+          "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9",
+          "references": "7997cf5a56cc02bdc9c93361bde732b0",
+          "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4",
+          "search": "db2c00e39b36f40930a3b9fc71c823e1",
+          "search-telemetry": "3d1b76c39bfb2cc8296b024d73854724",
+          "telemetry": "36a616f7026dfa617d6655df850fe16d",
+          "timelion-sheet": "9a2a2748877c7a7b582fef201ab1d4cf",
+          "type": "2f4316de49999235636386fe51dc06c1",
+          "ui-counter": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "updated_at": "00da57df13e94e9d98437d13ace4bfe0",
+          "url": "c7f66a0df8b1b52f17c28c4adb111105",
+          "usage-counters": "8cc260bdceffec4ffc3ad165c97dc1b4",
+          "visualization": "f819cf6636b75c9e76ba733a0c6ef355"
+        }
+      },
+      "dynamic": "strict",
       "properties": {
+        "application_usage_daily": {
+          "dynamic": "false",
+          "properties": {
+            "timestamp": {
+              "type": "date"
+            }
+          }
+        },
+        "application_usage_totals": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "application_usage_transactional": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "config": {
-          "dynamic": "true",
+          "dynamic": "false",
           "properties": {
             "buildNum": {
               "type": "keyword"
-            },
-            "dateFormat:tz": {
-              "fields": {
-                "keyword": {
-                  "ignore_above": 256,
-                  "type": "keyword"
-                }
-              },
-              "type": "text"
             }
           }
         },
+        "core-usage-stats": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "coreMigrationVersion": {
+          "type": "keyword"
+        },
         "dashboard": {
-          "dynamic": "strict",
           "properties": {
             "description": {
               "type": "text"
             },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "optionsJSON": {
+              "index": false,
               "type": "text"
             },
             "panelsJSON": {
+              "index": false,
               "type": "text"
             },
             "refreshInterval": {
               "properties": {
                 "display": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "keyword"
                 },
                 "pause": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "boolean"
                 },
                 "section": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 },
                 "value": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 }
               }
             },
             "timeFrom": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "timeRestore": {
+              "doc_values": false,
+              "index": false,
               "type": "boolean"
             },
             "timeTo": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
-            "uiStateJSON": {
-              "type": "text"
-            },
             "version": {
               "type": "integer"
             }
           }
         },
         "index-pattern": {
-          "dynamic": "strict",
+          "dynamic": "false",
           "properties": {
-            "fieldFormatMap": {
-              "type": "text"
-            },
-            "fields": {
+            "title": {
               "type": "text"
             },
-            "intervalName": {
+            "type": {
               "type": "keyword"
+            }
+          }
+        },
+        "kql-telemetry": {
+          "properties": {
+            "optInCount": {
+              "type": "long"
             },
-            "notExpandable": {
+            "optOutCount": {
+              "type": "long"
+            }
+          }
+        },
+        "legacy-url-alias": {
+          "dynamic": "false",
+          "properties": {
+            "disabled": {
               "type": "boolean"
             },
-            "sourceFilters": {
-              "type": "text"
+            "sourceId": {
+              "type": "keyword"
             },
-            "timeFieldName": {
+            "targetType": {
               "type": "keyword"
+            }
+          }
+        },
+        "migrationVersion": {
+          "dynamic": "true",
+          "type": "object"
+        },
+        "namespace": {
+          "type": "keyword"
+        },
+        "namespaces": {
+          "type": "keyword"
+        },
+        "originId": {
+          "type": "keyword"
+        },
+        "query": {
+          "properties": {
+            "description": {
+              "type": "text"
+            },
+            "filters": {
+              "enabled": false,
+              "type": "object"
+            },
+            "query": {
+              "properties": {
+                "language": {
+                  "type": "keyword"
+                },
+                "query": {
+                  "index": false,
+                  "type": "keyword"
+                }
+              }
+            },
+            "timefilter": {
+              "enabled": false,
+              "type": "object"
             },
             "title": {
               "type": "text"
             }
           }
         },
+        "references": {
+          "properties": {
+            "id": {
+              "type": "keyword"
+            },
+            "name": {
+              "type": "keyword"
+            },
+            "type": {
+              "type": "keyword"
+            }
+          },
+          "type": "nested"
+        },
+        "sample-data-telemetry": {
+          "properties": {
+            "installCount": {
+              "type": "long"
+            },
+            "unInstallCount": {
+              "type": "long"
+            }
+          }
+        },
         "search": {
-          "dynamic": "strict",
           "properties": {
             "columns": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "description": {
               "type": "text"
             },
+            "grid": {
+              "enabled": false,
+              "type": "object"
+            },
+            "hideChart": {
+              "doc_values": false,
+              "index": false,
+              "type": "boolean"
+            },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "sort": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
@@ -138,16 +291,47 @@
             }
           }
         },
+        "search-telemetry": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "server": {
-          "dynamic": "strict",
+          "dynamic": "false",
+          "type": "object"
+        },
+        "telemetry": {
           "properties": {
-            "uuid": {
+            "allowChangingOptInStatus": {
+              "type": "boolean"
+            },
+            "enabled": {
+              "type": "boolean"
+            },
+            "lastReported": {
+              "type": "date"
+            },
+            "lastVersionChecked": {
               "type": "keyword"
+            },
+            "reportFailureCount": {
+              "type": "integer"
+            },
+            "reportFailureVersion": {
+              "type": "keyword"
+            },
+            "sendUsageFrom": {
+              "type": "keyword"
+            },
+            "userHasSeenNotice": {
+              "type": "boolean"
             }
           }
         },
+        "test-deprecations-plugin": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "timelion-sheet": {
-          "dynamic": "strict",
           "properties": {
             "description": {
               "type": "text"
@@ -191,8 +375,24 @@
         "type": {
           "type": "keyword"
         },
+        "ui-counter": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
+        "ui-metric": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
+        "updated_at": {
+          "type": "date"
+        },
         "url": {
-          "dynamic": "strict",
           "properties": {
             "accessCount": {
               "type": "long"
@@ -214,8 +414,15 @@
             }
           }
         },
+        "usage-counters": {
+          "dynamic": "false",
+          "properties": {
+            "domainId": {
+              "type": "keyword"
+            }
+          }
+        },
         "visualization": {
-          "dynamic": "strict",
           "properties": {
             "description": {
               "type": "text"
@@ -223,59 +430,28 @@
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
-            "savedSearchId": {
+            "savedSearchRefName": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
             "uiStateJSON": {
+              "index": false,
               "type": "text"
             },
             "version": {
               "type": "integer"
             },
             "visState": {
-              "type": "text"
-            }
-          }
-        },
-        "query": {
-          "properties": {
-            "title": {
-              "type": "text"
-            },
-            "description": {
-              "type": "text"
-            },
-            "query": {
-              "properties": {
-                "language": {
-                  "type": "keyword"
-                },
-                "query": {
-                  "type": "keyword",
-                  "index": false
-                }
-              }
-            },
-            "filters": {
-              "type": "object",
-              "enabled": false
-            },
-            "timefilter": {
-              "type": "object",
-              "enabled": false
-            }
-          }
-        },
-        "test-deprecations-plugin": {
-          "properties": {
-            "title": {
+              "index": false,
               "type": "text"
             }
           }
@@ -284,9 +460,13 @@
     },
     "settings": {
       "index": {
+        "auto_expand_replicas": "0-1",
         "number_of_replicas": "0",
-        "number_of_shards": "1"
+        "number_of_shards": "1",
+        "priority": "10",
+        "refresh_interval": "1s",
+        "routing_partition_size": "1"
       }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/test/functional/fixtures/es_archiver/discover/data.json b/test/functional/fixtures/es_archiver/discover/data.json
index 0f2edc8c510c3..14a9f0559c6f3 100644
--- a/test/functional/fixtures/es_archiver/discover/data.json
+++ b/test/functional/fixtures/es_archiver/discover/data.json
@@ -4,14 +4,21 @@
     "id": "index-pattern:logstash-*",
     "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
       "index-pattern": {
+        "fieldAttrs": "{\"referer\":{\"customLabel\":\"Referer custom\"}}",
         "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"@message\"}}},{\"name\":\"@tags\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"@tags\"}}},{\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"agent\"}}},{\"name\":\"bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"extension\"}}},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"headings\"}}},{\"name\":\"host\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"host\"}}},{\"name\":\"id\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"index\"}}},{\"name\":\"ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"links\"}}},{\"name\":\"machine.os\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"machine.os\"}}},{\"name\":\"machine.ram\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"esTypes\":[\"double\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nestedField.child\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"nested\":{\"path\":\"nestedField\"}}},{\"name\":\"phpmemory\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.article:section\"}}},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.article:tag\"}}},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:description\"}}},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image\"}}},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image:height\"}}},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image:width\"}}},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:site_name\"}}},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:title\"}}},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:type\"}}},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:url\"}}},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:card\"}}},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:description\"}}},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:image\"}}},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:site\"}}},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:title\"}}},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.url\"}}},{\"name\":\"request\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"request\"}}},{\"name\":\"response\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"response\"}}},{\"name\":\"spaces\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"spaces\"}}},{\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"url\"}}},{\"name\":\"utc_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"xss\"}}}]",
         "timeFieldName": "@timestamp",
-        "title": "logstash-*",
-        "fieldAttrs": "{\"referer\":{\"customLabel\":\"Referer custom\"}}"
+        "title": "logstash-*"
       },
+      "migrationVersion": {
+        "index-pattern": "7.11.0"
+      },
+      "references": [
+      ],
       "type": "index-pattern"
-    }
+    },
+    "type": "_doc"
   }
 }
 
@@ -21,6 +28,17 @@
     "id": "search:ab12e3c0-f231-11e6-9486-733b1ac9221a",
     "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "search": "7.9.3"
+      },
+      "references": [
+        {
+          "id": "logstash-*",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
       "search": {
         "columns": [
           "_source"
@@ -28,16 +46,19 @@
         "description": "A Saved Search Description",
         "hits": 0,
         "kibanaSavedObjectMeta": {
-          "searchSourceJSON": "{\n \"index\": \"logstash-*\",\n \"highlightAll\": true,\n \"filter\": [],\n \"query\": {\n \"query_string\": {\n \"query\": \"*\",\n \"analyze_wildcard\": true\n }\n }\n}"
+          "searchSourceJSON": "{\"highlightAll\":true,\"filter\":[],\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
         },
         "sort": [
-          "@timestamp",
-          "desc"
+          [
+            "@timestamp",
+            "desc"
+          ]
         ],
         "title": "A Saved Search",
         "version": 1
       },
       "type": "search"
-    }
+    },
+    "type": "_doc"
   }
-}
+}
\ No newline at end of file
diff --git a/test/functional/fixtures/es_archiver/discover/mappings.json b/test/functional/fixtures/es_archiver/discover/mappings.json
index 519af2dd75b9e..93d724aa55603 100644
--- a/test/functional/fixtures/es_archiver/discover/mappings.json
+++ b/test/functional/fixtures/es_archiver/discover/mappings.json
@@ -2,126 +2,304 @@
   "type": "index",
   "value": {
     "aliases": {
+      ".kibana_$KIBANA_PACKAGE_VERSION": {},
       ".kibana": {}
     },
-    "index": ".kibana_1",
+    "index": ".kibana_$KIBANA_PACKAGE_VERSION_001",
     "mappings": {
+      "_meta": {
+        "migrationMappingPropertyHashes": {
+          "application_usage_daily": "43b8830d5d0df85a6823d290885fc9fd",
+          "application_usage_totals": "3d1b76c39bfb2cc8296b024d73854724",
+          "application_usage_transactional": "3d1b76c39bfb2cc8296b024d73854724",
+          "config": "c63748b75f39d0c54de12d12c1ccbc20",
+          "core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724",
+          "coreMigrationVersion": "2f4316de49999235636386fe51dc06c1",
+          "dashboard": "40554caf09725935e2c02e02563a2d07",
+          "index-pattern": "45915a1ad866812242df474eb0479052",
+          "kql-telemetry": "d12a98a6f19a2d273696597547e064ee",
+          "legacy-url-alias": "6155300fd11a00e23d5cbaa39f0fce0a",
+          "migrationVersion": "4a1746014a75ade3a714e1db5763276f",
+          "namespace": "2f4316de49999235636386fe51dc06c1",
+          "namespaces": "2f4316de49999235636386fe51dc06c1",
+          "originId": "2f4316de49999235636386fe51dc06c1",
+          "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9",
+          "references": "7997cf5a56cc02bdc9c93361bde732b0",
+          "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4",
+          "search": "db2c00e39b36f40930a3b9fc71c823e1",
+          "search-telemetry": "3d1b76c39bfb2cc8296b024d73854724",
+          "telemetry": "36a616f7026dfa617d6655df850fe16d",
+          "timelion-sheet": "9a2a2748877c7a7b582fef201ab1d4cf",
+          "type": "2f4316de49999235636386fe51dc06c1",
+          "ui-counter": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "updated_at": "00da57df13e94e9d98437d13ace4bfe0",
+          "url": "c7f66a0df8b1b52f17c28c4adb111105",
+          "usage-counters": "8cc260bdceffec4ffc3ad165c97dc1b4",
+          "visualization": "f819cf6636b75c9e76ba733a0c6ef355"
+        }
+      },
+      "dynamic": "strict",
       "properties": {
+        "application_usage_daily": {
+          "dynamic": "false",
+          "properties": {
+            "timestamp": {
+              "type": "date"
+            }
+          }
+        },
+        "application_usage_totals": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "application_usage_transactional": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "config": {
-          "dynamic": "true",
+          "dynamic": "false",
           "properties": {
             "buildNum": {
               "type": "keyword"
             }
           }
         },
+        "core-usage-stats": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "coreMigrationVersion": {
+          "type": "keyword"
+        },
         "dashboard": {
-          "dynamic": "strict",
           "properties": {
             "description": {
               "type": "text"
             },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "optionsJSON": {
+              "index": false,
               "type": "text"
             },
             "panelsJSON": {
+              "index": false,
               "type": "text"
             },
             "refreshInterval": {
               "properties": {
                 "display": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "keyword"
                 },
                 "pause": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "boolean"
                 },
                 "section": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 },
                 "value": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 }
               }
             },
             "timeFrom": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "timeRestore": {
+              "doc_values": false,
+              "index": false,
               "type": "boolean"
             },
             "timeTo": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
-            "uiStateJSON": {
-              "type": "text"
-            },
             "version": {
               "type": "integer"
             }
           }
         },
         "index-pattern": {
-          "dynamic": "strict",
+          "dynamic": "false",
           "properties": {
-            "fieldFormatMap": {
-              "type": "text"
-            },
-            "fields": {
+            "title": {
               "type": "text"
             },
-            "intervalName": {
+            "type": {
               "type": "keyword"
+            }
+          }
+        },
+        "kql-telemetry": {
+          "properties": {
+            "optInCount": {
+              "type": "long"
             },
-            "notExpandable": {
+            "optOutCount": {
+              "type": "long"
+            }
+          }
+        },
+        "legacy-url-alias": {
+          "dynamic": "false",
+          "properties": {
+            "disabled": {
               "type": "boolean"
             },
-            "sourceFilters": {
-              "type": "text"
+            "sourceId": {
+              "type": "keyword"
             },
-            "timeFieldName": {
+            "targetType": {
               "type": "keyword"
+            }
+          }
+        },
+        "migrationVersion": {
+          "dynamic": "true",
+          "properties": {
+            "index-pattern": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
             },
-            "title": {
+            "search": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
               "type": "text"
+            }
+          }
+        },
+        "namespace": {
+          "type": "keyword"
+        },
+        "namespaces": {
+          "type": "keyword"
+        },
+        "originId": {
+          "type": "keyword"
+        },
+        "query": {
+          "properties": {
+            "description": {
+              "type": "text"
+            },
+            "filters": {
+              "enabled": false,
+              "type": "object"
+            },
+            "query": {
+              "properties": {
+                "language": {
+                  "type": "keyword"
+                },
+                "query": {
+                  "index": false,
+                  "type": "keyword"
+                }
+              }
+            },
+            "timefilter": {
+              "enabled": false,
+              "type": "object"
             },
-            "fieldAttrs": {
+            "title": {
               "type": "text"
             }
           }
         },
+        "references": {
+          "properties": {
+            "id": {
+              "type": "keyword"
+            },
+            "name": {
+              "type": "keyword"
+            },
+            "type": {
+              "type": "keyword"
+            }
+          },
+          "type": "nested"
+        },
+        "sample-data-telemetry": {
+          "properties": {
+            "installCount": {
+              "type": "long"
+            },
+            "unInstallCount": {
+              "type": "long"
+            }
+          }
+        },
         "search": {
-          "dynamic": "strict",
           "properties": {
             "columns": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "description": {
               "type": "text"
             },
+            "grid": {
+              "enabled": false,
+              "type": "object"
+            },
+            "hideChart": {
+              "doc_values": false,
+              "index": false,
+              "type": "boolean"
+            },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "sort": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
@@ -132,16 +310,43 @@
             }
           }
         },
+        "search-telemetry": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "server": {
-          "dynamic": "strict",
+          "dynamic": "false",
+          "type": "object"
+        },
+        "telemetry": {
           "properties": {
-            "uuid": {
+            "allowChangingOptInStatus": {
+              "type": "boolean"
+            },
+            "enabled": {
+              "type": "boolean"
+            },
+            "lastReported": {
+              "type": "date"
+            },
+            "lastVersionChecked": {
+              "type": "keyword"
+            },
+            "reportFailureCount": {
+              "type": "integer"
+            },
+            "reportFailureVersion": {
+              "type": "keyword"
+            },
+            "sendUsageFrom": {
               "type": "keyword"
+            },
+            "userHasSeenNotice": {
+              "type": "boolean"
             }
           }
         },
         "timelion-sheet": {
-          "dynamic": "strict",
           "properties": {
             "description": {
               "type": "text"
@@ -185,8 +390,24 @@
         "type": {
           "type": "keyword"
         },
+        "ui-counter": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
+        "ui-metric": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
+        "updated_at": {
+          "type": "date"
+        },
         "url": {
-          "dynamic": "strict",
           "properties": {
             "accessCount": {
               "type": "long"
@@ -208,8 +429,15 @@
             }
           }
         },
+        "usage-counters": {
+          "dynamic": "false",
+          "properties": {
+            "domainId": {
+              "type": "keyword"
+            }
+          }
+        },
         "visualization": {
-          "dynamic": "strict",
           "properties": {
             "description": {
               "type": "text"
@@ -217,63 +445,43 @@
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
-            "savedSearchId": {
+            "savedSearchRefName": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
             "uiStateJSON": {
+              "index": false,
               "type": "text"
             },
             "version": {
               "type": "integer"
             },
             "visState": {
+              "index": false,
               "type": "text"
             }
           }
-        },
-        "query": {
-          "properties": {
-            "title": {
-              "type": "text"
-            },
-            "description": {
-              "type": "text"
-            },
-            "query": {
-              "properties": {
-                "language": {
-                  "type": "keyword"
-                },
-                "query": {
-                  "type": "keyword",
-                  "index": false
-                }
-              }
-            },
-            "filters": {
-              "type": "object",
-              "enabled": false
-            },
-            "timefilter": {
-              "type": "object",
-              "enabled": false
-            }
-          }
         }
       }
     },
     "settings": {
       "index": {
-        "number_of_replicas": "1",
-        "number_of_shards": "1"
+        "auto_expand_replicas": "0-1",
+        "number_of_replicas": "0",
+        "number_of_shards": "1",
+        "priority": "10",
+        "refresh_interval": "1s",
+        "routing_partition_size": "1"
       }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/export_transform/data.json b/test/functional/fixtures/es_archiver/saved_objects_management/export_transform/data.json
index 7f4043958bc89..54feabcf54331 100644
--- a/test/functional/fixtures/es_archiver/saved_objects_management/export_transform/data.json
+++ b/test/functional/fixtures/es_archiver/saved_objects_management/export_transform/data.json
@@ -1,149 +1,161 @@
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
-    "type": "doc",
     "id": "test-export-transform:type_1-obj_1",
+    "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
       "test-export-transform": {
-        "title": "test_1-obj_1",
-        "enabled": true
+        "enabled": true,
+        "title": "test_1-obj_1"
       },
       "type": "test-export-transform",
-      "migrationVersion": {},
       "updated_at": "2018-12-21T00:43:07.096Z"
-    }
+    },
+    "type": "_doc"
   }
 }
 
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
-    "type": "doc",
     "id": "test-export-transform:type_1-obj_2",
+    "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
       "test-export-transform": {
-        "title": "test_1-obj_2",
-        "enabled": true
+        "enabled": true,
+        "title": "test_1-obj_2"
       },
       "type": "test-export-transform",
-      "migrationVersion": {},
       "updated_at": "2018-12-21T00:43:07.096Z"
-    }
+    },
+    "type": "_doc"
   }
 }
 
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
-    "type": "doc",
     "id": "test-export-add:type_2-obj_1",
+    "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
       "test-export-add": {
         "title": "test_2-obj_1"
       },
       "type": "test-export-add",
-      "migrationVersion": {},
       "updated_at": "2018-12-21T00:43:07.096Z"
-    }
+    },
+    "type": "_doc"
   }
 }
 
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
-    "type": "doc",
     "id": "test-export-add:type_2-obj_2",
+    "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
       "test-export-add": {
         "title": "test_2-obj_2"
       },
       "type": "test-export-add",
-      "migrationVersion": {},
       "updated_at": "2018-12-21T00:43:07.096Z"
-    }
+    },
+    "type": "_doc"
   }
 }
 
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
-    "type": "doc",
     "id": "test-export-add-dep:type_dep-obj_1",
+    "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+        {
+          "id": "type_2-obj_1",
+          "type": "test-export-add"
+        }
+      ],
       "test-export-add-dep": {
         "title": "type_dep-obj_1"
       },
       "type": "test-export-add-dep",
-      "migrationVersion": {},
-      "updated_at": "2018-12-21T00:43:07.096Z",
-      "references": [
-        {
-          "type": "test-export-add",
-          "id": "type_2-obj_1"
-        }
-      ]
-    }
+      "updated_at": "2018-12-21T00:43:07.096Z"
+    },
+    "type": "_doc"
   }
 }
 
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
-    "type": "doc",
     "id": "test-export-add-dep:type_dep-obj_2",
+    "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+        {
+          "id": "type_2-obj_2",
+          "type": "test-export-add"
+        }
+      ],
       "test-export-add-dep": {
         "title": "type_dep-obj_2"
       },
       "type": "test-export-add-dep",
-      "migrationVersion": {},
-      "updated_at": "2018-12-21T00:43:07.096Z",
-      "references": [
-        {
-          "type": "test-export-add",
-          "id": "type_2-obj_2"
-        }
-      ]
-    }
+      "updated_at": "2018-12-21T00:43:07.096Z"
+    },
+    "type": "_doc"
   }
 }
 
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
-    "type": "doc",
     "id": "test-export-invalid-transform:type_3-obj_1",
+    "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
       "test-export-invalid-transform": {
         "title": "test_2-obj_1"
       },
       "type": "test-export-invalid-transform",
-      "migrationVersion": {},
       "updated_at": "2018-12-21T00:43:07.096Z"
-    }
+    },
+    "type": "_doc"
   }
 }
 
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
-    "type": "doc",
     "id": "test-export-transform-error:type_4-obj_1",
+    "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
       "test-export-transform-error": {
         "title": "test_2-obj_1"
       },
       "type": "test-export-transform-error",
-      "migrationVersion": {},
       "updated_at": "2018-12-21T00:43:07.096Z"
-    }
+    },
+    "type": "_doc"
   }
-}
+}
\ No newline at end of file
diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/export_transform/mappings.json b/test/functional/fixtures/es_archiver/saved_objects_management/export_transform/mappings.json
index 653e639954813..b2385a281dd23 100644
--- a/test/functional/fixtures/es_archiver/saved_objects_management/export_transform/mappings.json
+++ b/test/functional/fixtures/es_archiver/saved_objects_management/export_transform/mappings.json
@@ -2,333 +2,301 @@
   "type": "index",
   "value": {
     "aliases": {
+      ".kibana_$KIBANA_PACKAGE_VERSION": {},
       ".kibana": {}
     },
-    "index": ".kibana_1",
-    "settings": {
-      "index": {
-        "number_of_shards": "1",
-        "auto_expand_replicas": "0-1",
-        "number_of_replicas": "0"
-      }
-    },
+    "index": ".kibana_$KIBANA_PACKAGE_VERSION_001",
     "mappings": {
+      "_meta": {
+        "migrationMappingPropertyHashes": {
+          "application_usage_daily": "43b8830d5d0df85a6823d290885fc9fd",
+          "application_usage_totals": "3d1b76c39bfb2cc8296b024d73854724",
+          "application_usage_transactional": "3d1b76c39bfb2cc8296b024d73854724",
+          "config": "c63748b75f39d0c54de12d12c1ccbc20",
+          "core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724",
+          "coreMigrationVersion": "2f4316de49999235636386fe51dc06c1",
+          "dashboard": "40554caf09725935e2c02e02563a2d07",
+          "index-pattern": "45915a1ad866812242df474eb0479052",
+          "kql-telemetry": "d12a98a6f19a2d273696597547e064ee",
+          "legacy-url-alias": "6155300fd11a00e23d5cbaa39f0fce0a",
+          "migrationVersion": "4a1746014a75ade3a714e1db5763276f",
+          "namespace": "2f4316de49999235636386fe51dc06c1",
+          "namespaces": "2f4316de49999235636386fe51dc06c1",
+          "originId": "2f4316de49999235636386fe51dc06c1",
+          "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9",
+          "references": "7997cf5a56cc02bdc9c93361bde732b0",
+          "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4",
+          "search": "db2c00e39b36f40930a3b9fc71c823e1",
+          "search-telemetry": "3d1b76c39bfb2cc8296b024d73854724",
+          "telemetry": "36a616f7026dfa617d6655df850fe16d",
+          "timelion-sheet": "9a2a2748877c7a7b582fef201ab1d4cf",
+          "type": "2f4316de49999235636386fe51dc06c1",
+          "ui-counter": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "updated_at": "00da57df13e94e9d98437d13ace4bfe0",
+          "url": "c7f66a0df8b1b52f17c28c4adb111105",
+          "usage-counters": "8cc260bdceffec4ffc3ad165c97dc1b4",
+          "visualization": "f819cf6636b75c9e76ba733a0c6ef355"
+        }
+      },
       "dynamic": "strict",
       "properties": {
-        "test-export-transform": {
-          "properties": {
-            "title": { "type": "text" },
-            "enabled": { "type": "boolean" }
-          }
-        },
-        "test-export-add": {
-          "properties": {
-            "title": { "type": "text" }
-          }
-        },
-        "test-export-add-dep": {
-          "properties": {
-            "title": { "type": "text" }
-          }
+        "apm-telemetry": {
+          "dynamic": "false",
+          "type": "object"
         },
-        "test-export-transform-error": {
+        "application_usage_daily": {
+          "dynamic": "false",
           "properties": {
-            "title": { "type": "text" }
+            "timestamp": {
+              "type": "date"
+            }
           }
         },
-        "test-export-invalid-transform": {
-          "properties": {
-            "title": { "type": "text" }
-          }
+        "application_usage_totals": {
+          "dynamic": "false",
+          "type": "object"
         },
-        "apm-telemetry": {
-          "properties": {
-            "has_any_services": {
-              "type": "boolean"
-            },
-            "services_per_agent": {
-              "properties": {
-                "go": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "java": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "js-base": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "nodejs": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "python": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "ruby": {
-                  "type": "long",
-                  "null_value": 0
-                }
-              }
-            }
-          }
+        "application_usage_transactional": {
+          "dynamic": "false",
+          "type": "object"
         },
         "canvas-workpad": {
           "dynamic": "false",
-          "properties": {
-            "@created": {
-              "type": "date"
-            },
-            "@timestamp": {
-              "type": "date"
-            },
-            "id": {
-              "type": "text",
-              "index": false
-            },
-            "name": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword"
-                }
-              }
-            }
-          }
+          "type": "object"
         },
         "config": {
-          "dynamic": "true",
+          "dynamic": "false",
           "properties": {
-            "accessibility:disableAnimations": {
-              "type": "boolean"
-            },
             "buildNum": {
               "type": "keyword"
-            },
-            "dateFormat:tz": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 256
-                }
-              }
-            },
-            "defaultIndex": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 256
-                }
-              }
-            },
-            "telemetry:optIn": {
-              "type": "boolean"
             }
           }
         },
+        "core-usage-stats": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "coreMigrationVersion": {
+          "type": "keyword"
+        },
         "dashboard": {
           "properties": {
             "description": {
               "type": "text"
             },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "optionsJSON": {
+              "index": false,
               "type": "text"
             },
             "panelsJSON": {
+              "index": false,
               "type": "text"
             },
             "refreshInterval": {
               "properties": {
                 "display": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "keyword"
                 },
                 "pause": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "boolean"
                 },
                 "section": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 },
                 "value": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 }
               }
             },
             "timeFrom": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "timeRestore": {
+              "doc_values": false,
+              "index": false,
               "type": "boolean"
             },
             "timeTo": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
-            "uiStateJSON": {
-              "type": "text"
-            },
             "version": {
               "type": "integer"
             }
           }
         },
-        "map": {
+        "graph-workspace": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "index-pattern": {
+          "dynamic": "false",
           "properties": {
-            "bounds": {
-              "dynamic": false,
-              "properties": {}
-            },
-            "description": {
-              "type": "text"
-            },
-            "layerListJSON": {
+            "title": {
               "type": "text"
             },
-            "mapStateJSON": {
-              "type": "text"
+            "type": {
+              "type": "keyword"
+            }
+          }
+        },
+        "kql-telemetry": {
+          "properties": {
+            "optInCount": {
+              "type": "long"
             },
-            "title": {
-              "type": "text"
+            "optOutCount": {
+              "type": "long"
+            }
+          }
+        },
+        "legacy-url-alias": {
+          "dynamic": "false",
+          "properties": {
+            "disabled": {
+              "type": "boolean"
             },
-            "uiStateJSON": {
-              "type": "text"
+            "sourceId": {
+              "type": "keyword"
             },
-            "version": {
-              "type": "integer"
+            "targetType": {
+              "type": "keyword"
             }
           }
         },
-        "graph-workspace": {
+        "map": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "migrationVersion": {
+          "dynamic": "true",
+          "type": "object"
+        },
+        "namespace": {
+          "type": "keyword"
+        },
+        "namespaces": {
+          "type": "keyword"
+        },
+        "originId": {
+          "type": "keyword"
+        },
+        "query": {
           "properties": {
             "description": {
               "type": "text"
             },
-            "kibanaSavedObjectMeta": {
+            "filters": {
+              "enabled": false,
+              "type": "object"
+            },
+            "query": {
               "properties": {
-                "searchSourceJSON": {
-                  "type": "text"
+                "language": {
+                  "type": "keyword"
+                },
+                "query": {
+                  "index": false,
+                  "type": "keyword"
                 }
               }
             },
-            "numLinks": {
-              "type": "integer"
-            },
-            "numVertices": {
-              "type": "integer"
+            "timefilter": {
+              "enabled": false,
+              "type": "object"
             },
             "title": {
               "type": "text"
-            },
-            "version": {
-              "type": "integer"
-            },
-            "wsState": {
-              "type": "text"
             }
           }
         },
-        "index-pattern": {
+        "references": {
           "properties": {
-            "fieldFormatMap": {
-              "type": "text"
-            },
-            "fields": {
-              "type": "text"
-            },
-            "intervalName": {
+            "id": {
               "type": "keyword"
             },
-            "notExpandable": {
-              "type": "boolean"
-            },
-            "sourceFilters": {
-              "type": "text"
-            },
-            "timeFieldName": {
+            "name": {
               "type": "keyword"
             },
-            "title": {
-              "type": "text"
-            },
             "type": {
               "type": "keyword"
-            },
-            "typeMeta": {
-              "type": "keyword"
             }
-          }
+          },
+          "type": "nested"
         },
-        "kql-telemetry": {
+        "sample-data-telemetry": {
           "properties": {
-            "optInCount": {
+            "installCount": {
               "type": "long"
             },
-            "optOutCount": {
+            "unInstallCount": {
               "type": "long"
             }
           }
         },
-        "migrationVersion": {
-          "dynamic": "true",
-          "properties": {
-            "index-pattern": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 256
-                }
-              }
-            },
-            "space": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 256
-                }
-              }
-            }
-          }
-        },
-        "namespace": {
-          "type": "keyword"
-        },
         "search": {
           "properties": {
             "columns": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "description": {
               "type": "text"
             },
+            "grid": {
+              "enabled": false,
+              "type": "object"
+            },
+            "hideChart": {
+              "doc_values": false,
+              "index": false,
+              "type": "boolean"
+            },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "sort": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
@@ -339,50 +307,68 @@
             }
           }
         },
+        "search-telemetry": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "server": {
-          "properties": {
-            "uuid": {
-              "type": "keyword"
-            }
-          }
+          "dynamic": "false",
+          "type": "object"
         },
         "space": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "spaceId": {
+          "type": "keyword"
+        },
+        "telemetry": {
           "properties": {
-            "_reserved": {
+            "allowChangingOptInStatus": {
+              "type": "boolean"
+            },
+            "enabled": {
               "type": "boolean"
             },
-            "color": {
+            "lastReported": {
+              "type": "date"
+            },
+            "lastVersionChecked": {
               "type": "keyword"
             },
-            "description": {
-              "type": "text"
+            "reportFailureCount": {
+              "type": "integer"
             },
-            "disabledFeatures": {
+            "reportFailureVersion": {
               "type": "keyword"
             },
-            "initials": {
+            "sendUsageFrom": {
               "type": "keyword"
             },
-            "name": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 2048
-                }
-              }
+            "userHasSeenNotice": {
+              "type": "boolean"
             }
           }
         },
-        "spaceId": {
-          "type": "keyword"
+        "test-export-add": {
+          "dynamic": "false",
+          "type": "object"
         },
-        "telemetry": {
-          "properties": {
-            "enabled": {
-              "type": "boolean"
-            }
-          }
+        "test-export-add-dep": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "test-export-invalid-transform": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "test-export-transform": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "test-export-transform-error": {
+          "dynamic": "false",
+          "type": "object"
         },
         "timelion-sheet": {
           "properties": {
@@ -428,6 +414,20 @@
         "type": {
           "type": "keyword"
         },
+        "ui-counter": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
+        "ui-metric": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
         "updated_at": {
           "type": "date"
         },
@@ -443,13 +443,21 @@
               "type": "date"
             },
             "url": {
-              "type": "text",
               "fields": {
                 "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 2048
+                  "ignore_above": 2048,
+                  "type": "keyword"
                 }
-              }
+              },
+              "type": "text"
+            }
+          }
+        },
+        "usage-counters": {
+          "dynamic": "false",
+          "properties": {
+            "domainId": {
+              "type": "keyword"
             }
           }
         },
@@ -461,42 +469,43 @@
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
-            "savedSearchId": {
+            "savedSearchRefName": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
             "uiStateJSON": {
+              "index": false,
               "type": "text"
             },
             "version": {
               "type": "integer"
             },
             "visState": {
+              "index": false,
               "type": "text"
             }
           }
-        },
-        "references": {
-          "properties": {
-            "id": {
-              "type": "keyword"
-            },
-            "name": {
-              "type": "keyword"
-            },
-            "type": {
-              "type": "keyword"
-            }
-          },
-          "type": "nested"
         }
       }
+    },
+    "settings": {
+      "index": {
+        "auto_expand_replicas": "0-1",
+        "number_of_replicas": "0",
+        "number_of_shards": "1",
+        "priority": "10",
+        "refresh_interval": "1s",
+        "routing_partition_size": "1"
+      }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/data.json b/test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/data.json
index 6a272dc16e462..4996c050adbf0 100644
--- a/test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/data.json
+++ b/test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/data.json
@@ -1,29 +1,37 @@
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
     "id": "test-hidden-importable-exportable:ff3733a0-9fty-11e7-ahb3-3dcb94193fab",
+    "index": ".kibana",
     "source": {
-      "type": "test-hidden-importable-exportable",
-      "updated_at": "2021-02-11T18:51:23.794Z",
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
       "test-hidden-importable-exportable": {
         "title": "Hidden Saved object type that is importable/exportable."
-      }
-    }
+      },
+      "type": "test-hidden-importable-exportable",
+      "updated_at": "2021-02-11T18:51:23.794Z"
+    },
+    "type": "_doc"
   }
 }
 
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
     "id": "test-hidden-non-importable-exportable:op3767a1-9rcg-53u7-jkb3-3dnb74193awc",
+    "index": ".kibana",
     "source": {
-      "type": "test-hidden-non-importable-exportable",
-      "updated_at": "2021-02-11T18:51:23.794Z",
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
       "test-hidden-non-importable-exportable": {
         "title": "Hidden Saved object type that is not importable/exportable."
-      }
-    }
+      },
+      "type": "test-hidden-non-importable-exportable",
+      "updated_at": "2021-02-11T18:51:23.794Z"
+    },
+    "type": "_doc"
   }
-}
+}
\ No newline at end of file
diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/mappings.json b/test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/mappings.json
index a158deb527cc8..d59f3b00d4818 100644
--- a/test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/mappings.json
+++ b/test/functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects/mappings.json
@@ -2,333 +2,301 @@
   "type": "index",
   "value": {
     "aliases": {
+      ".kibana_$KIBANA_PACKAGE_VERSION": {},
       ".kibana": {}
     },
-    "index": ".kibana_1",
-    "settings": {
-      "index": {
-        "number_of_shards": "1",
-        "auto_expand_replicas": "0-1",
-        "number_of_replicas": "0"
-      }
-    },
+    "index": ".kibana_$KIBANA_PACKAGE_VERSION_001",
     "mappings": {
+      "_meta": {
+        "migrationMappingPropertyHashes": {
+          "application_usage_daily": "43b8830d5d0df85a6823d290885fc9fd",
+          "application_usage_totals": "3d1b76c39bfb2cc8296b024d73854724",
+          "application_usage_transactional": "3d1b76c39bfb2cc8296b024d73854724",
+          "config": "c63748b75f39d0c54de12d12c1ccbc20",
+          "core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724",
+          "coreMigrationVersion": "2f4316de49999235636386fe51dc06c1",
+          "dashboard": "40554caf09725935e2c02e02563a2d07",
+          "index-pattern": "45915a1ad866812242df474eb0479052",
+          "kql-telemetry": "d12a98a6f19a2d273696597547e064ee",
+          "legacy-url-alias": "6155300fd11a00e23d5cbaa39f0fce0a",
+          "migrationVersion": "4a1746014a75ade3a714e1db5763276f",
+          "namespace": "2f4316de49999235636386fe51dc06c1",
+          "namespaces": "2f4316de49999235636386fe51dc06c1",
+          "originId": "2f4316de49999235636386fe51dc06c1",
+          "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9",
+          "references": "7997cf5a56cc02bdc9c93361bde732b0",
+          "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4",
+          "search": "db2c00e39b36f40930a3b9fc71c823e1",
+          "search-telemetry": "3d1b76c39bfb2cc8296b024d73854724",
+          "telemetry": "36a616f7026dfa617d6655df850fe16d",
+          "timelion-sheet": "9a2a2748877c7a7b582fef201ab1d4cf",
+          "type": "2f4316de49999235636386fe51dc06c1",
+          "ui-counter": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "updated_at": "00da57df13e94e9d98437d13ace4bfe0",
+          "url": "c7f66a0df8b1b52f17c28c4adb111105",
+          "usage-counters": "8cc260bdceffec4ffc3ad165c97dc1b4",
+          "visualization": "f819cf6636b75c9e76ba733a0c6ef355"
+        }
+      },
       "dynamic": "strict",
       "properties": {
-        "test-export-transform": {
-          "properties": {
-            "title": { "type": "text" },
-            "enabled": { "type": "boolean" }
-          }
-        },
-        "test-export-add": {
-          "properties": {
-            "title": { "type": "text" }
-          }
-        },
-        "test-export-add-dep": {
-          "properties": {
-            "title": { "type": "text" }
-          }
+        "apm-telemetry": {
+          "dynamic": "false",
+          "type": "object"
         },
-        "test-export-transform-error": {
+        "application_usage_daily": {
+          "dynamic": "false",
           "properties": {
-            "title": { "type": "text" }
+            "timestamp": {
+              "type": "date"
+            }
           }
         },
-        "test-export-invalid-transform": {
-          "properties": {
-            "title": { "type": "text" }
-          }
+        "application_usage_totals": {
+          "dynamic": "false",
+          "type": "object"
         },
-        "apm-telemetry": {
-          "properties": {
-            "has_any_services": {
-              "type": "boolean"
-            },
-            "services_per_agent": {
-              "properties": {
-                "go": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "java": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "js-base": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "nodejs": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "python": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "ruby": {
-                  "type": "long",
-                  "null_value": 0
-                }
-              }
-            }
-          }
+        "application_usage_transactional": {
+          "dynamic": "false",
+          "type": "object"
         },
         "canvas-workpad": {
           "dynamic": "false",
-          "properties": {
-            "@created": {
-              "type": "date"
-            },
-            "@timestamp": {
-              "type": "date"
-            },
-            "id": {
-              "type": "text",
-              "index": false
-            },
-            "name": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword"
-                }
-              }
-            }
-          }
+          "type": "object"
         },
         "config": {
-          "dynamic": "true",
+          "dynamic": "false",
           "properties": {
-            "accessibility:disableAnimations": {
-              "type": "boolean"
-            },
             "buildNum": {
               "type": "keyword"
-            },
-            "dateFormat:tz": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 256
-                }
-              }
-            },
-            "defaultIndex": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 256
-                }
-              }
-            },
-            "telemetry:optIn": {
-              "type": "boolean"
             }
           }
         },
+        "core-usage-stats": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "coreMigrationVersion": {
+          "type": "keyword"
+        },
         "dashboard": {
           "properties": {
             "description": {
               "type": "text"
             },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "optionsJSON": {
+              "index": false,
               "type": "text"
             },
             "panelsJSON": {
+              "index": false,
               "type": "text"
             },
             "refreshInterval": {
               "properties": {
                 "display": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "keyword"
                 },
                 "pause": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "boolean"
                 },
                 "section": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 },
                 "value": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 }
               }
             },
             "timeFrom": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "timeRestore": {
+              "doc_values": false,
+              "index": false,
               "type": "boolean"
             },
             "timeTo": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
-            "uiStateJSON": {
-              "type": "text"
-            },
             "version": {
               "type": "integer"
             }
           }
         },
-        "map": {
+        "graph-workspace": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "index-pattern": {
+          "dynamic": "false",
           "properties": {
-            "bounds": {
-              "dynamic": false,
-              "properties": {}
-            },
-            "description": {
-              "type": "text"
-            },
-            "layerListJSON": {
+            "title": {
               "type": "text"
             },
-            "mapStateJSON": {
-              "type": "text"
+            "type": {
+              "type": "keyword"
+            }
+          }
+        },
+        "kql-telemetry": {
+          "properties": {
+            "optInCount": {
+              "type": "long"
             },
-            "title": {
-              "type": "text"
+            "optOutCount": {
+              "type": "long"
+            }
+          }
+        },
+        "legacy-url-alias": {
+          "dynamic": "false",
+          "properties": {
+            "disabled": {
+              "type": "boolean"
             },
-            "uiStateJSON": {
-              "type": "text"
+            "sourceId": {
+              "type": "keyword"
             },
-            "version": {
-              "type": "integer"
+            "targetType": {
+              "type": "keyword"
             }
           }
         },
-        "graph-workspace": {
+        "map": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "migrationVersion": {
+          "dynamic": "true",
+          "type": "object"
+        },
+        "namespace": {
+          "type": "keyword"
+        },
+        "namespaces": {
+          "type": "keyword"
+        },
+        "originId": {
+          "type": "keyword"
+        },
+        "query": {
           "properties": {
             "description": {
               "type": "text"
             },
-            "kibanaSavedObjectMeta": {
+            "filters": {
+              "enabled": false,
+              "type": "object"
+            },
+            "query": {
               "properties": {
-                "searchSourceJSON": {
-                  "type": "text"
+                "language": {
+                  "type": "keyword"
+                },
+                "query": {
+                  "index": false,
+                  "type": "keyword"
                 }
               }
             },
-            "numLinks": {
-              "type": "integer"
-            },
-            "numVertices": {
-              "type": "integer"
+            "timefilter": {
+              "enabled": false,
+              "type": "object"
             },
             "title": {
               "type": "text"
-            },
-            "version": {
-              "type": "integer"
-            },
-            "wsState": {
-              "type": "text"
             }
           }
         },
-        "index-pattern": {
+        "references": {
           "properties": {
-            "fieldFormatMap": {
-              "type": "text"
-            },
-            "fields": {
-              "type": "text"
-            },
-            "intervalName": {
+            "id": {
               "type": "keyword"
             },
-            "notExpandable": {
-              "type": "boolean"
-            },
-            "sourceFilters": {
-              "type": "text"
-            },
-            "timeFieldName": {
+            "name": {
               "type": "keyword"
             },
-            "title": {
-              "type": "text"
-            },
             "type": {
               "type": "keyword"
-            },
-            "typeMeta": {
-              "type": "keyword"
             }
-          }
+          },
+          "type": "nested"
         },
-        "kql-telemetry": {
+        "sample-data-telemetry": {
           "properties": {
-            "optInCount": {
+            "installCount": {
               "type": "long"
             },
-            "optOutCount": {
+            "unInstallCount": {
               "type": "long"
             }
           }
         },
-        "migrationVersion": {
-          "dynamic": "true",
-          "properties": {
-            "index-pattern": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 256
-                }
-              }
-            },
-            "space": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 256
-                }
-              }
-            }
-          }
-        },
-        "namespace": {
-          "type": "keyword"
-        },
         "search": {
           "properties": {
             "columns": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "description": {
               "type": "text"
             },
+            "grid": {
+              "enabled": false,
+              "type": "object"
+            },
+            "hideChart": {
+              "doc_values": false,
+              "index": false,
+              "type": "boolean"
+            },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "sort": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
@@ -339,50 +307,76 @@
             }
           }
         },
+        "search-telemetry": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "server": {
-          "properties": {
-            "uuid": {
-              "type": "keyword"
-            }
-          }
+          "dynamic": "false",
+          "type": "object"
         },
         "space": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "spaceId": {
+          "type": "keyword"
+        },
+        "telemetry": {
           "properties": {
-            "_reserved": {
+            "allowChangingOptInStatus": {
               "type": "boolean"
             },
-            "color": {
+            "enabled": {
+              "type": "boolean"
+            },
+            "lastReported": {
+              "type": "date"
+            },
+            "lastVersionChecked": {
               "type": "keyword"
             },
-            "description": {
-              "type": "text"
+            "reportFailureCount": {
+              "type": "integer"
             },
-            "disabledFeatures": {
+            "reportFailureVersion": {
               "type": "keyword"
             },
-            "initials": {
+            "sendUsageFrom": {
               "type": "keyword"
             },
-            "name": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 2048
-                }
-              }
+            "userHasSeenNotice": {
+              "type": "boolean"
             }
           }
         },
-        "spaceId": {
-          "type": "keyword"
+        "test-export-add": {
+          "dynamic": "false",
+          "type": "object"
         },
-        "telemetry": {
-          "properties": {
-            "enabled": {
-              "type": "boolean"
-            }
-          }
+        "test-export-add-dep": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "test-export-invalid-transform": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "test-export-transform": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "test-export-transform-error": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "test-hidden-importable-exportable": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "test-hidden-non-importable-exportable": {
+          "dynamic": "false",
+          "type": "object"
         },
         "timelion-sheet": {
           "properties": {
@@ -428,6 +422,20 @@
         "type": {
           "type": "keyword"
         },
+        "ui-counter": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
+        "ui-metric": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
         "updated_at": {
           "type": "date"
         },
@@ -443,13 +451,21 @@
               "type": "date"
             },
             "url": {
-              "type": "text",
               "fields": {
                 "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 2048
+                  "ignore_above": 2048,
+                  "type": "keyword"
                 }
-              }
+              },
+              "type": "text"
+            }
+          }
+        },
+        "usage-counters": {
+          "dynamic": "false",
+          "properties": {
+            "domainId": {
+              "type": "keyword"
             }
           }
         },
@@ -461,56 +477,43 @@
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
-            "savedSearchId": {
+            "savedSearchRefName": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
             "uiStateJSON": {
+              "index": false,
               "type": "text"
             },
             "version": {
               "type": "integer"
             },
             "visState": {
-              "type": "text"
-            }
-          }
-        },
-        "references": {
-          "properties": {
-            "id": {
-              "type": "keyword"
-            },
-            "name": {
-              "type": "keyword"
-            },
-            "type": {
-              "type": "keyword"
-            }
-          },
-          "type": "nested"
-        },
-        "test-hidden-non-importable-exportable": {
-          "properties": {
-            "title": {
-              "type": "text"
-            }
-          }
-        },
-        "test-hidden-importable-exportable": {
-          "properties": {
-            "title": {
+              "index": false,
               "type": "text"
             }
           }
         }
       }
+    },
+    "settings": {
+      "index": {
+        "auto_expand_replicas": "0-1",
+        "number_of_replicas": "0",
+        "number_of_shards": "1",
+        "priority": "10",
+        "refresh_interval": "1s",
+        "routing_partition_size": "1"
+      }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/nested_export_transform/data.json b/test/functional/fixtures/es_archiver/saved_objects_management/nested_export_transform/data.json
index caac89461b9ef..3c311b0465193 100644
--- a/test/functional/fixtures/es_archiver/saved_objects_management/nested_export_transform/data.json
+++ b/test/functional/fixtures/es_archiver/saved_objects_management/nested_export_transform/data.json
@@ -1,87 +1,91 @@
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
-    "type": "doc",
     "id": "test-export-transform:type_1-obj_1",
+    "index": ".kibana",
     "source": {
-      "test-export-transform": {
-        "title": "test_1-obj_1",
-        "enabled": true
-      },
-      "type": "test-export-transform",
-      "migrationVersion": {},
-      "updated_at": "2018-12-21T00:43:07.096Z",
+      "coreMigrationVersion": "7.14.0",
       "references": [
         {
-          "type": "test-export-transform",
           "id": "type_1-obj_2",
-          "name": "ref-1"
+          "name": "ref-1",
+          "type": "test-export-transform"
         },
         {
-          "type": "test-export-add",
           "id": "type_2-obj_1",
-          "name": "ref-2"
+          "name": "ref-2",
+          "type": "test-export-add"
         }
-      ]
-    }
+      ],
+      "test-export-transform": {
+        "enabled": true,
+        "title": "test_1-obj_1"
+      },
+      "type": "test-export-transform",
+      "updated_at": "2018-12-21T00:43:07.096Z"
+    },
+    "type": "_doc"
   }
 }
 
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
-    "type": "doc",
     "id": "test-export-transform:type_1-obj_2",
+    "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
       "test-export-transform": {
-        "title": "test_1-obj_2",
-        "enabled": true
+        "enabled": true,
+        "title": "test_1-obj_2"
       },
       "type": "test-export-transform",
-      "migrationVersion": {},
       "updated_at": "2018-12-21T00:43:07.096Z"
-    }
+    },
+    "type": "_doc"
   }
 }
 
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
-    "type": "doc",
     "id": "test-export-add:type_2-obj_1",
+    "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+      ],
       "test-export-add": {
         "title": "test_2-obj_1"
       },
       "type": "test-export-add",
-      "migrationVersion": {},
       "updated_at": "2018-12-21T00:43:07.096Z"
-    }
+    },
+    "type": "_doc"
   }
 }
 
 {
   "type": "doc",
   "value": {
-    "index": ".kibana",
-    "type": "doc",
     "id": "test-export-add-dep:type_dep-obj_1",
+    "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "references": [
+        {
+          "id": "type_2-obj_1",
+          "type": "test-export-add"
+        }
+      ],
       "test-export-add-dep": {
         "title": "type_dep-obj_1"
       },
       "type": "test-export-add-dep",
-      "migrationVersion": {},
-      "updated_at": "2018-12-21T00:43:07.096Z",
-      "references": [
-        {
-          "type": "test-export-add",
-          "id": "type_2-obj_1"
-        }
-      ]
-    }
+      "updated_at": "2018-12-21T00:43:07.096Z"
+    },
+    "type": "_doc"
   }
-}
+}
\ No newline at end of file
diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/nested_export_transform/mappings.json b/test/functional/fixtures/es_archiver/saved_objects_management/nested_export_transform/mappings.json
index 653e639954813..b2385a281dd23 100644
--- a/test/functional/fixtures/es_archiver/saved_objects_management/nested_export_transform/mappings.json
+++ b/test/functional/fixtures/es_archiver/saved_objects_management/nested_export_transform/mappings.json
@@ -2,333 +2,301 @@
   "type": "index",
   "value": {
     "aliases": {
+      ".kibana_$KIBANA_PACKAGE_VERSION": {},
       ".kibana": {}
     },
-    "index": ".kibana_1",
-    "settings": {
-      "index": {
-        "number_of_shards": "1",
-        "auto_expand_replicas": "0-1",
-        "number_of_replicas": "0"
-      }
-    },
+    "index": ".kibana_$KIBANA_PACKAGE_VERSION_001",
     "mappings": {
+      "_meta": {
+        "migrationMappingPropertyHashes": {
+          "application_usage_daily": "43b8830d5d0df85a6823d290885fc9fd",
+          "application_usage_totals": "3d1b76c39bfb2cc8296b024d73854724",
+          "application_usage_transactional": "3d1b76c39bfb2cc8296b024d73854724",
+          "config": "c63748b75f39d0c54de12d12c1ccbc20",
+          "core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724",
+          "coreMigrationVersion": "2f4316de49999235636386fe51dc06c1",
+          "dashboard": "40554caf09725935e2c02e02563a2d07",
+          "index-pattern": "45915a1ad866812242df474eb0479052",
+          "kql-telemetry": "d12a98a6f19a2d273696597547e064ee",
+          "legacy-url-alias": "6155300fd11a00e23d5cbaa39f0fce0a",
+          "migrationVersion": "4a1746014a75ade3a714e1db5763276f",
+          "namespace": "2f4316de49999235636386fe51dc06c1",
+          "namespaces": "2f4316de49999235636386fe51dc06c1",
+          "originId": "2f4316de49999235636386fe51dc06c1",
+          "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9",
+          "references": "7997cf5a56cc02bdc9c93361bde732b0",
+          "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4",
+          "search": "db2c00e39b36f40930a3b9fc71c823e1",
+          "search-telemetry": "3d1b76c39bfb2cc8296b024d73854724",
+          "telemetry": "36a616f7026dfa617d6655df850fe16d",
+          "timelion-sheet": "9a2a2748877c7a7b582fef201ab1d4cf",
+          "type": "2f4316de49999235636386fe51dc06c1",
+          "ui-counter": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "updated_at": "00da57df13e94e9d98437d13ace4bfe0",
+          "url": "c7f66a0df8b1b52f17c28c4adb111105",
+          "usage-counters": "8cc260bdceffec4ffc3ad165c97dc1b4",
+          "visualization": "f819cf6636b75c9e76ba733a0c6ef355"
+        }
+      },
       "dynamic": "strict",
       "properties": {
-        "test-export-transform": {
-          "properties": {
-            "title": { "type": "text" },
-            "enabled": { "type": "boolean" }
-          }
-        },
-        "test-export-add": {
-          "properties": {
-            "title": { "type": "text" }
-          }
-        },
-        "test-export-add-dep": {
-          "properties": {
-            "title": { "type": "text" }
-          }
+        "apm-telemetry": {
+          "dynamic": "false",
+          "type": "object"
         },
-        "test-export-transform-error": {
+        "application_usage_daily": {
+          "dynamic": "false",
           "properties": {
-            "title": { "type": "text" }
+            "timestamp": {
+              "type": "date"
+            }
           }
         },
-        "test-export-invalid-transform": {
-          "properties": {
-            "title": { "type": "text" }
-          }
+        "application_usage_totals": {
+          "dynamic": "false",
+          "type": "object"
         },
-        "apm-telemetry": {
-          "properties": {
-            "has_any_services": {
-              "type": "boolean"
-            },
-            "services_per_agent": {
-              "properties": {
-                "go": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "java": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "js-base": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "nodejs": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "python": {
-                  "type": "long",
-                  "null_value": 0
-                },
-                "ruby": {
-                  "type": "long",
-                  "null_value": 0
-                }
-              }
-            }
-          }
+        "application_usage_transactional": {
+          "dynamic": "false",
+          "type": "object"
         },
         "canvas-workpad": {
           "dynamic": "false",
-          "properties": {
-            "@created": {
-              "type": "date"
-            },
-            "@timestamp": {
-              "type": "date"
-            },
-            "id": {
-              "type": "text",
-              "index": false
-            },
-            "name": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword"
-                }
-              }
-            }
-          }
+          "type": "object"
         },
         "config": {
-          "dynamic": "true",
+          "dynamic": "false",
           "properties": {
-            "accessibility:disableAnimations": {
-              "type": "boolean"
-            },
             "buildNum": {
               "type": "keyword"
-            },
-            "dateFormat:tz": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 256
-                }
-              }
-            },
-            "defaultIndex": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 256
-                }
-              }
-            },
-            "telemetry:optIn": {
-              "type": "boolean"
             }
           }
         },
+        "core-usage-stats": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "coreMigrationVersion": {
+          "type": "keyword"
+        },
         "dashboard": {
           "properties": {
             "description": {
               "type": "text"
             },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "optionsJSON": {
+              "index": false,
               "type": "text"
             },
             "panelsJSON": {
+              "index": false,
               "type": "text"
             },
             "refreshInterval": {
               "properties": {
                 "display": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "keyword"
                 },
                 "pause": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "boolean"
                 },
                 "section": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 },
                 "value": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 }
               }
             },
             "timeFrom": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "timeRestore": {
+              "doc_values": false,
+              "index": false,
               "type": "boolean"
             },
             "timeTo": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
-            "uiStateJSON": {
-              "type": "text"
-            },
             "version": {
               "type": "integer"
             }
           }
         },
-        "map": {
+        "graph-workspace": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "index-pattern": {
+          "dynamic": "false",
           "properties": {
-            "bounds": {
-              "dynamic": false,
-              "properties": {}
-            },
-            "description": {
-              "type": "text"
-            },
-            "layerListJSON": {
+            "title": {
               "type": "text"
             },
-            "mapStateJSON": {
-              "type": "text"
+            "type": {
+              "type": "keyword"
+            }
+          }
+        },
+        "kql-telemetry": {
+          "properties": {
+            "optInCount": {
+              "type": "long"
             },
-            "title": {
-              "type": "text"
+            "optOutCount": {
+              "type": "long"
+            }
+          }
+        },
+        "legacy-url-alias": {
+          "dynamic": "false",
+          "properties": {
+            "disabled": {
+              "type": "boolean"
             },
-            "uiStateJSON": {
-              "type": "text"
+            "sourceId": {
+              "type": "keyword"
             },
-            "version": {
-              "type": "integer"
+            "targetType": {
+              "type": "keyword"
             }
           }
         },
-        "graph-workspace": {
+        "map": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "migrationVersion": {
+          "dynamic": "true",
+          "type": "object"
+        },
+        "namespace": {
+          "type": "keyword"
+        },
+        "namespaces": {
+          "type": "keyword"
+        },
+        "originId": {
+          "type": "keyword"
+        },
+        "query": {
           "properties": {
             "description": {
               "type": "text"
             },
-            "kibanaSavedObjectMeta": {
+            "filters": {
+              "enabled": false,
+              "type": "object"
+            },
+            "query": {
               "properties": {
-                "searchSourceJSON": {
-                  "type": "text"
+                "language": {
+                  "type": "keyword"
+                },
+                "query": {
+                  "index": false,
+                  "type": "keyword"
                 }
               }
             },
-            "numLinks": {
-              "type": "integer"
-            },
-            "numVertices": {
-              "type": "integer"
+            "timefilter": {
+              "enabled": false,
+              "type": "object"
             },
             "title": {
               "type": "text"
-            },
-            "version": {
-              "type": "integer"
-            },
-            "wsState": {
-              "type": "text"
             }
           }
         },
-        "index-pattern": {
+        "references": {
           "properties": {
-            "fieldFormatMap": {
-              "type": "text"
-            },
-            "fields": {
-              "type": "text"
-            },
-            "intervalName": {
+            "id": {
               "type": "keyword"
             },
-            "notExpandable": {
-              "type": "boolean"
-            },
-            "sourceFilters": {
-              "type": "text"
-            },
-            "timeFieldName": {
+            "name": {
               "type": "keyword"
             },
-            "title": {
-              "type": "text"
-            },
             "type": {
               "type": "keyword"
-            },
-            "typeMeta": {
-              "type": "keyword"
             }
-          }
+          },
+          "type": "nested"
         },
-        "kql-telemetry": {
+        "sample-data-telemetry": {
           "properties": {
-            "optInCount": {
+            "installCount": {
               "type": "long"
             },
-            "optOutCount": {
+            "unInstallCount": {
               "type": "long"
             }
           }
         },
-        "migrationVersion": {
-          "dynamic": "true",
-          "properties": {
-            "index-pattern": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 256
-                }
-              }
-            },
-            "space": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 256
-                }
-              }
-            }
-          }
-        },
-        "namespace": {
-          "type": "keyword"
-        },
         "search": {
           "properties": {
             "columns": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "description": {
               "type": "text"
             },
+            "grid": {
+              "enabled": false,
+              "type": "object"
+            },
+            "hideChart": {
+              "doc_values": false,
+              "index": false,
+              "type": "boolean"
+            },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "sort": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
@@ -339,50 +307,68 @@
             }
           }
         },
+        "search-telemetry": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "server": {
-          "properties": {
-            "uuid": {
-              "type": "keyword"
-            }
-          }
+          "dynamic": "false",
+          "type": "object"
         },
         "space": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "spaceId": {
+          "type": "keyword"
+        },
+        "telemetry": {
           "properties": {
-            "_reserved": {
+            "allowChangingOptInStatus": {
+              "type": "boolean"
+            },
+            "enabled": {
               "type": "boolean"
             },
-            "color": {
+            "lastReported": {
+              "type": "date"
+            },
+            "lastVersionChecked": {
               "type": "keyword"
             },
-            "description": {
-              "type": "text"
+            "reportFailureCount": {
+              "type": "integer"
             },
-            "disabledFeatures": {
+            "reportFailureVersion": {
               "type": "keyword"
             },
-            "initials": {
+            "sendUsageFrom": {
               "type": "keyword"
             },
-            "name": {
-              "type": "text",
-              "fields": {
-                "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 2048
-                }
-              }
+            "userHasSeenNotice": {
+              "type": "boolean"
             }
           }
         },
-        "spaceId": {
-          "type": "keyword"
+        "test-export-add": {
+          "dynamic": "false",
+          "type": "object"
         },
-        "telemetry": {
-          "properties": {
-            "enabled": {
-              "type": "boolean"
-            }
-          }
+        "test-export-add-dep": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "test-export-invalid-transform": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "test-export-transform": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "test-export-transform-error": {
+          "dynamic": "false",
+          "type": "object"
         },
         "timelion-sheet": {
           "properties": {
@@ -428,6 +414,20 @@
         "type": {
           "type": "keyword"
         },
+        "ui-counter": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
+        "ui-metric": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
         "updated_at": {
           "type": "date"
         },
@@ -443,13 +443,21 @@
               "type": "date"
             },
             "url": {
-              "type": "text",
               "fields": {
                 "keyword": {
-                  "type": "keyword",
-                  "ignore_above": 2048
+                  "ignore_above": 2048,
+                  "type": "keyword"
                 }
-              }
+              },
+              "type": "text"
+            }
+          }
+        },
+        "usage-counters": {
+          "dynamic": "false",
+          "properties": {
+            "domainId": {
+              "type": "keyword"
             }
           }
         },
@@ -461,42 +469,43 @@
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
-            "savedSearchId": {
+            "savedSearchRefName": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
             "uiStateJSON": {
+              "index": false,
               "type": "text"
             },
             "version": {
               "type": "integer"
             },
             "visState": {
+              "index": false,
               "type": "text"
             }
           }
-        },
-        "references": {
-          "properties": {
-            "id": {
-              "type": "keyword"
-            },
-            "name": {
-              "type": "keyword"
-            },
-            "type": {
-              "type": "keyword"
-            }
-          },
-          "type": "nested"
         }
       }
+    },
+    "settings": {
+      "index": {
+        "auto_expand_replicas": "0-1",
+        "number_of_replicas": "0",
+        "number_of_shards": "1",
+        "priority": "10",
+        "refresh_interval": "1s",
+        "routing_partition_size": "1"
+      }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/test/functional/fixtures/es_archiver/visualize/data.json b/test/functional/fixtures/es_archiver/visualize/data.json
index f337bffe80f2c..d48aa3e98d18a 100644
--- a/test/functional/fixtures/es_archiver/visualize/data.json
+++ b/test/functional/fixtures/es_archiver/visualize/data.json
@@ -4,15 +4,22 @@
     "id": "index-pattern:logstash-*",
     "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
       "index-pattern": {
+        "fieldAttrs": "{\"utc_time\":{\"customLabel\":\"UTC time\"}}",
         "fieldFormatMap": "{\"bytes\":{\"id\":\"bytes\"}}",
         "fields": "[{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false}]",
         "timeFieldName": "@timestamp",
-        "title": "logstash-*",
-        "fieldAttrs": "{\"utc_time\":{\"customLabel\":\"UTC time\"}}"
+        "title": "logstash-*"
       },
+      "migrationVersion": {
+        "index-pattern": "7.11.0"
+      },
+      "references": [
+      ],
       "type": "index-pattern"
-    }
+    },
+    "type": "_doc"
   }
 }
 
@@ -22,13 +29,20 @@
     "id": "index-pattern:logstash*",
     "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
       "index-pattern": {
         "fieldFormatMap": "{\"bytes\":{\"id\":\"bytes\"}}",
         "fields": "[{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false}]",
         "title": "logstash*"
       },
+      "migrationVersion": {
+        "index-pattern": "7.11.0"
+      },
+      "references": [
+      ],
       "type": "index-pattern"
-    }
+    },
+    "type": "_doc"
   }
 }
 
@@ -38,14 +52,21 @@
     "id": "index-pattern:long-window-logstash-*",
     "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
       "index-pattern": {
         "fieldFormatMap": "{\"bytes\":{\"id\":\"bytes\"}}",
         "fields": "[{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false}]",
         "timeFieldName": "@timestamp",
         "title": "long-window-logstash-*"
       },
+      "migrationVersion": {
+        "index-pattern": "7.11.0"
+      },
+      "references": [
+      ],
       "type": "index-pattern"
-    }
+    },
+    "type": "_doc"
   }
 }
 
@@ -55,18 +76,30 @@
     "id": "visualization:Shared-Item-Visualization-AreaChart",
     "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "logstash-*",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
       "type": "visualization",
       "visualization": {
         "description": "AreaChart",
         "kibanaSavedObjectMeta": {
-          "searchSourceJSON": "{\"index\":\"logstash-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}"
+          "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
         },
         "title": "Shared-Item Visualization AreaChart",
         "uiStateJSON": "{}",
         "version": 1,
-        "visState": "{\"title\":\"New Visualization\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}"
+        "visState": "{\"title\":\"New Visualization\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}"
       }
-    }
+    },
+    "type": "_doc"
   }
 }
 
@@ -76,18 +109,30 @@
     "id": "visualization:Visualization-AreaChart",
     "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "logstash-*",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
       "type": "visualization",
       "visualization": {
         "description": "AreaChart",
         "kibanaSavedObjectMeta": {
-          "searchSourceJSON": "{\"index\":\"logstash-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}"
+          "searchSourceJSON": "{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
         },
         "title": "Visualization AreaChart",
         "uiStateJSON": "{}",
         "version": 1,
-        "visState": "{\"title\":\"Visualization AreaChart\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"labels\":{}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-15m\",\"to\":\"now\"},\"useNormalizedEsInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}}]}"
+        "visState": "{\"title\":\"Visualization AreaChart\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"labels\":{},\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"fittingFunction\":\"zero\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"now-15m\",\"to\":\"now\"},\"useNormalizedEsInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}}]}"
       }
-    }
+    },
+    "type": "_doc"
   }
 }
 
@@ -97,34 +142,36 @@
     "id": "visualization:68305470-87bc-11e9-a991-3b492a7c3e09",
     "index": ".kibana",
     "source": {
-      "visualization" : {
-        "title" : "chained input control",
-        "visState" : "{\"title\":\"chained input control\",\"type\":\"input_control_vis\",\"params\":{\"controls\":[{\"id\":\"1559757816862\",\"fieldName\":\"geo.src\",\"parent\":\"\",\"label\":\"\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"dynamicOptions\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_0_index_pattern\"},{\"id\":\"1559757836347\",\"fieldName\":\"clientip\",\"parent\":\"1559757816862\",\"label\":\"\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"dynamicOptions\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_1_index_pattern\"}],\"updateFiltersOnChange\":false,\"useTimeFilter\":false,\"pinFilters\":false},\"aggs\":[]}",
-        "uiStateJSON" : "{}",
-        "description" : "",
-        "version" : 1,
-        "kibanaSavedObjectMeta" : {
-          "searchSourceJSON" : "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"
-        }
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
       },
-      "type" : "visualization",
-      "references" : [
+      "references": [
         {
-          "name" : "control_0_index_pattern",
-          "type" : "index-pattern",
-          "id" : "logstash-*"
+          "id": "logstash-*",
+          "name": "control_0_index_pattern",
+          "type": "index-pattern"
         },
         {
-          "name" : "control_1_index_pattern",
-          "type" : "index-pattern",
-          "id" : "logstash-*"
+          "id": "logstash-*",
+          "name": "control_1_index_pattern",
+          "type": "index-pattern"
         }
       ],
-      "migrationVersion" : {
-        "visualization" : "7.3.0"
-      },
-      "updated_at" : "2019-06-05T18:04:48.310Z"
-    }
+      "type": "visualization",
+      "updated_at": "2019-06-05T18:04:48.310Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"
+        },
+        "title": "chained input control",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"chained input control\",\"type\":\"input_control_vis\",\"params\":{\"controls\":[{\"id\":\"1559757816862\",\"fieldName\":\"geo.src\",\"parent\":\"\",\"label\":\"\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"dynamicOptions\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_0_index_pattern\"},{\"id\":\"1559757836347\",\"fieldName\":\"clientip\",\"parent\":\"1559757816862\",\"label\":\"\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"dynamicOptions\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_1_index_pattern\"}],\"updateFiltersOnChange\":false,\"useTimeFilter\":false,\"pinFilters\":false},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
   }
 }
 
@@ -134,29 +181,31 @@
     "id": "visualization:64983230-87bf-11e9-a991-3b492a7c3e09",
     "index": ".kibana",
     "source": {
-      "visualization" : {
-        "title" : "dynamic options input control",
-        "visState" : "{\"title\":\"dynamic options input control\",\"type\":\"input_control_vis\",\"params\":{\"controls\":[{\"id\":\"1559759127876\",\"fieldName\":\"geo.src\",\"parent\":\"\",\"label\":\"\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"dynamicOptions\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_0_index_pattern\"}],\"updateFiltersOnChange\":false,\"useTimeFilter\":false,\"pinFilters\":false},\"aggs\":[]}",
-        "uiStateJSON" : "{}",
-        "description" : "",
-        "version" : 1,
-        "kibanaSavedObjectMeta" : {
-          "searchSourceJSON" : "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"
-        }
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
       },
-      "type" : "visualization",
-      "references" : [
+      "references": [
         {
-          "name" : "control_0_index_pattern",
-          "type" : "index-pattern",
-          "id" : "logstash-*"
+          "id": "logstash-*",
+          "name": "control_0_index_pattern",
+          "type": "index-pattern"
         }
       ],
-      "migrationVersion" : {
-        "visualization" : "7.3.0"
-      },
-      "updated_at" : "2019-06-05T18:26:10.771Z"
-    }
+      "type": "visualization",
+      "updated_at": "2019-06-05T18:26:10.771Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"
+        },
+        "title": "dynamic options input control",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"dynamic options input control\",\"type\":\"input_control_vis\",\"params\":{\"controls\":[{\"id\":\"1559759127876\",\"fieldName\":\"geo.src\",\"parent\":\"\",\"label\":\"\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"dynamicOptions\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_0_index_pattern\"}],\"updateFiltersOnChange\":false,\"useTimeFilter\":false,\"pinFilters\":false},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
   }
 }
 
@@ -166,34 +215,36 @@
     "id": "visualization:5d2de430-87c0-11e9-a991-3b492a7c3e09",
     "index": ".kibana",
     "source": {
-      "visualization" : {
-        "title" : "chained input control with dynamic options",
-        "visState" : "{\"title\":\"chained input control with dynamic options\",\"type\":\"input_control_vis\",\"params\":{\"controls\":[{\"id\":\"1559759550755\",\"fieldName\":\"machine.os.raw\",\"parent\":\"\",\"label\":\"\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"dynamicOptions\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_0_index_pattern\"},{\"id\":\"1559759557302\",\"fieldName\":\"geo.src\",\"parent\":\"1559759550755\",\"label\":\"\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"dynamicOptions\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_1_index_pattern\"}],\"updateFiltersOnChange\":false,\"useTimeFilter\":false,\"pinFilters\":false},\"aggs\":[]}",
-        "uiStateJSON" : "{}",
-        "description" : "",
-        "version" : 1,
-        "kibanaSavedObjectMeta" : {
-          "searchSourceJSON" : "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"
-        }
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
       },
-      "type" : "visualization",
-      "references" : [
+      "references": [
         {
-          "name" : "control_0_index_pattern",
-          "type" : "index-pattern",
-          "id" : "logstash-*"
+          "id": "logstash-*",
+          "name": "control_0_index_pattern",
+          "type": "index-pattern"
         },
         {
-          "name" : "control_1_index_pattern",
-          "type" : "index-pattern",
-          "id" : "logstash-*"
+          "id": "logstash-*",
+          "name": "control_1_index_pattern",
+          "type": "index-pattern"
         }
       ],
-      "migrationVersion" : {
-        "visualization" : "7.3.0"
-      },
-      "updated_at" : "2019-06-05T18:33:07.827Z"
-    }
+      "type": "visualization",
+      "updated_at": "2019-06-05T18:33:07.827Z",
+      "visualization": {
+        "description": "",
+        "kibanaSavedObjectMeta": {
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"
+        },
+        "title": "chained input control with dynamic options",
+        "uiStateJSON": "{}",
+        "version": 1,
+        "visState": "{\"title\":\"chained input control with dynamic options\",\"type\":\"input_control_vis\",\"params\":{\"controls\":[{\"id\":\"1559759550755\",\"fieldName\":\"machine.os.raw\",\"parent\":\"\",\"label\":\"\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"dynamicOptions\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_0_index_pattern\"},{\"id\":\"1559759557302\",\"fieldName\":\"geo.src\",\"parent\":\"1559759550755\",\"label\":\"\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"dynamicOptions\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_1_index_pattern\"}],\"updateFiltersOnChange\":false,\"useTimeFilter\":false,\"pinFilters\":false},\"aggs\":[]}"
+      }
+    },
+    "type": "_doc"
   }
 }
 
@@ -203,12 +254,19 @@
     "id": "index-pattern:test_index*",
     "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
       "index-pattern": {
         "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"message.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"message\"}}},{\"name\":\"user\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"user.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"user\"}}}]",
         "title": "test_index*"
       },
+      "migrationVersion": {
+        "index-pattern": "7.11.0"
+      },
+      "references": [
+      ],
       "type": "index-pattern"
-    }
+    },
+    "type": "_doc"
   }
 }
 
@@ -218,18 +276,30 @@
     "id": "visualization:AreaChart-no-date-field",
     "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "test_index*",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
       "type": "visualization",
       "visualization": {
         "description": "AreaChart",
         "kibanaSavedObjectMeta": {
-          "searchSourceJSON": "{\"index\":\"test_index*\",\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
         },
         "title": "AreaChart [no date field]",
         "uiStateJSON": "{}",
         "version": 1,
-        "visState": "{\"title\":\"AreaChart [no date field]\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"addTooltip\":true,\"addLegend\":true,\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}]}"
-        }
-    }
+        "visState": "{\"title\":\"AreaChart [no date field]\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"addTooltip\":true,\"addLegend\":true,\"times\":[],\"addTimeMarker\":false,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"fittingFunction\":\"zero\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}]}"
+      }
+    },
+    "type": "_doc"
   }
 }
 
@@ -239,13 +309,20 @@
     "id": "index-pattern:log*",
     "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
       "index-pattern": {
         "fieldFormatMap": "{\"bytes\":{\"id\":\"bytes\"}}",
         "fields": "[{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false}]",
         "title": "log*"
       },
+      "migrationVersion": {
+        "index-pattern": "7.11.0"
+      },
+      "references": [
+      ],
       "type": "index-pattern"
-    }
+    },
+    "type": "_doc"
   }
 }
 
@@ -255,18 +332,30 @@
     "id": "visualization:AreaChart-no-time-filter",
     "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+        {
+          "id": "log*",
+          "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
+          "type": "index-pattern"
+        }
+      ],
       "type": "visualization",
       "visualization": {
         "description": "AreaChart",
         "kibanaSavedObjectMeta": {
-          "searchSourceJSON": "{\"index\":\"log*\",\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"
+          "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
         },
         "title": "AreaChart [no time filter]",
         "uiStateJSON": "{}",
         "version": 1,
-        "visState": "{\"title\":\"AreaChart [no time filter]\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"addTooltip\":true,\"addLegend\":true,\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}]}"
-        }
-    }
+        "visState": "{\"title\":\"AreaChart [no time filter]\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"addTooltip\":true,\"addLegend\":true,\"times\":[],\"addTimeMarker\":false,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"fittingFunction\":\"zero\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}]}"
+      }
+    },
+    "type": "_doc"
   }
 }
 
@@ -276,6 +365,12 @@
     "id": "visualization:VegaMap",
     "index": ".kibana",
     "source": {
+      "coreMigrationVersion": "7.14.0",
+      "migrationVersion": {
+        "visualization": "7.14.0"
+      },
+      "references": [
+      ],
       "type": "visualization",
       "visualization": {
         "description": "VegaMap",
@@ -287,6 +382,7 @@
         "version": 1,
         "visState": "{\"aggs\":[],\"params\":{\"spec\":\"{\\n  $schema: https://vega.github.io/schema/vega/v5.json\\n  config: {\\n    kibana: {type: \\\"map\\\", latitude: 25, longitude: -70, zoom: 3}\\n  }\\n  data: [\\n    {\\n      name: table\\n      url: {\\n        index: kibana_sample_data_flights\\n        %context%: true\\n        // Uncomment to enable time filtering\\n        // %timefield%: timestamp\\n        body: {\\n          size: 0\\n          aggs: {\\n            origins: {\\n              terms: {field: \\\"OriginAirportID\\\", size: 10000}\\n              aggs: {\\n                originLocation: {\\n                  top_hits: {\\n                    size: 1\\n                    _source: {\\n                      includes: [\\\"OriginLocation\\\", \\\"Origin\\\"]\\n                    }\\n                  }\\n                }\\n                distinations: {\\n                  terms: {field: \\\"DestAirportID\\\", size: 10000}\\n                  aggs: {\\n                    destLocation: {\\n                      top_hits: {\\n                        size: 1\\n                        _source: {\\n                          includes: [\\\"DestLocation\\\"]\\n                        }\\n                      }\\n                    }\\n                  }\\n                }\\n              }\\n            }\\n          }\\n        }\\n      }\\n      format: {property: \\\"aggregations.origins.buckets\\\"}\\n      transform: [\\n        {\\n          type: geopoint\\n          projection: projection\\n          fields: [\\n            originLocation.hits.hits[0]._source.OriginLocation.lon\\n            originLocation.hits.hits[0]._source.OriginLocation.lat\\n          ]\\n        }\\n      ]\\n    }\\n    {\\n      name: selectedDatum\\n      on: [\\n        {trigger: \\\"!selected\\\", remove: true}\\n        {trigger: \\\"selected\\\", insert: \\\"selected\\\"}\\n      ]\\n    }\\n  ]\\n  signals: [\\n    {\\n      name: selected\\n      value: null\\n      on: [\\n        {events: \\\"@airport:mouseover\\\", update: \\\"datum\\\"}\\n        {events: \\\"@airport:mouseout\\\", update: \\\"null\\\"}\\n      ]\\n    }\\n  ]\\n  scales: [\\n    {\\n      name: airportSize\\n      type: linear\\n      domain: {data: \\\"table\\\", field: \\\"doc_count\\\"}\\n      range: [\\n        {signal: \\\"zoom*zoom*0.2+1\\\"}\\n        {signal: \\\"zoom*zoom*10+1\\\"}\\n      ]\\n    }\\n  ]\\n  marks: [\\n    {\\n      type: group\\n      from: {\\n        facet: {\\n          name: facetedDatum\\n          data: selectedDatum\\n          field: distinations.buckets\\n        }\\n      }\\n      data: [\\n        {\\n          name: facetDatumElems\\n          source: facetedDatum\\n          transform: [\\n            {\\n              type: geopoint\\n              projection: projection\\n              fields: [\\n                destLocation.hits.hits[0]._source.DestLocation.lon\\n                destLocation.hits.hits[0]._source.DestLocation.lat\\n              ]\\n            }\\n            {type: \\\"formula\\\", expr: \\\"{x:parent.x, y:parent.y}\\\", as: \\\"source\\\"}\\n            {type: \\\"formula\\\", expr: \\\"{x:datum.x, y:datum.y}\\\", as: \\\"target\\\"}\\n            {type: \\\"linkpath\\\", shape: \\\"diagonal\\\"}\\n          ]\\n        }\\n      ]\\n      scales: [\\n        {\\n          name: lineThickness\\n          type: log\\n          clamp: true\\n          range: [1, 8]\\n        }\\n        {\\n          name: lineOpacity\\n          type: log\\n          clamp: true\\n          range: [0.2, 0.8]\\n        }\\n      ]\\n      marks: [\\n        {\\n          from: {data: \\\"facetDatumElems\\\"}\\n          type: path\\n          interactive: false\\n          encode: {\\n            update: {\\n              path: {field: \\\"path\\\"}\\n              stroke: {value: \\\"black\\\"}\\n              strokeWidth: {scale: \\\"lineThickness\\\", field: \\\"doc_count\\\"}\\n              strokeOpacity: {scale: \\\"lineOpacity\\\", field: \\\"doc_count\\\"}\\n            }\\n          }\\n        }\\n      ]\\n    }\\n    {\\n      name: airport\\n      type: symbol\\n      from: {data: \\\"table\\\"}\\n      encode: {\\n        update: {\\n          size: {scale: \\\"airportSize\\\", field: \\\"doc_count\\\"}\\n          xc: {signal: \\\"datum.x\\\"}\\n          yc: {signal: \\\"datum.y\\\"}\\n          tooltip: {\\n            signal: \\\"{title: datum.originLocation.hits.hits[0]._source.Origin + ' (' + datum.key + ')', connnections: length(datum.distinations.buckets), flights: datum.doc_count}\\\"\\n          }\\n        }\\n      }\\n    }\\n  ]\\n}\"},\"title\":\"[Flights] Airport Connections (Hover Over Airport)\",\"type\":\"vega\"}"
       }
-    }
+    },
+    "type": "_doc"
   }
-}
+}
\ No newline at end of file
diff --git a/test/functional/fixtures/es_archiver/visualize/mappings.json b/test/functional/fixtures/es_archiver/visualize/mappings.json
index 59ec24853e227..d032352d9a688 100644
--- a/test/functional/fixtures/es_archiver/visualize/mappings.json
+++ b/test/functional/fixtures/es_archiver/visualize/mappings.json
@@ -2,126 +2,304 @@
   "type": "index",
   "value": {
     "aliases": {
+      ".kibana_$KIBANA_PACKAGE_VERSION": {},
       ".kibana": {}
     },
-    "index": ".kibana_1",
+    "index": ".kibana_$KIBANA_PACKAGE_VERSION_001",
     "mappings": {
+      "_meta": {
+        "migrationMappingPropertyHashes": {
+          "application_usage_daily": "43b8830d5d0df85a6823d290885fc9fd",
+          "application_usage_totals": "3d1b76c39bfb2cc8296b024d73854724",
+          "application_usage_transactional": "3d1b76c39bfb2cc8296b024d73854724",
+          "config": "c63748b75f39d0c54de12d12c1ccbc20",
+          "core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724",
+          "coreMigrationVersion": "2f4316de49999235636386fe51dc06c1",
+          "dashboard": "40554caf09725935e2c02e02563a2d07",
+          "index-pattern": "45915a1ad866812242df474eb0479052",
+          "kql-telemetry": "d12a98a6f19a2d273696597547e064ee",
+          "legacy-url-alias": "6155300fd11a00e23d5cbaa39f0fce0a",
+          "migrationVersion": "4a1746014a75ade3a714e1db5763276f",
+          "namespace": "2f4316de49999235636386fe51dc06c1",
+          "namespaces": "2f4316de49999235636386fe51dc06c1",
+          "originId": "2f4316de49999235636386fe51dc06c1",
+          "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9",
+          "references": "7997cf5a56cc02bdc9c93361bde732b0",
+          "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4",
+          "search": "db2c00e39b36f40930a3b9fc71c823e1",
+          "search-telemetry": "3d1b76c39bfb2cc8296b024d73854724",
+          "telemetry": "36a616f7026dfa617d6655df850fe16d",
+          "timelion-sheet": "9a2a2748877c7a7b582fef201ab1d4cf",
+          "type": "2f4316de49999235636386fe51dc06c1",
+          "ui-counter": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3",
+          "updated_at": "00da57df13e94e9d98437d13ace4bfe0",
+          "url": "c7f66a0df8b1b52f17c28c4adb111105",
+          "usage-counters": "8cc260bdceffec4ffc3ad165c97dc1b4",
+          "visualization": "f819cf6636b75c9e76ba733a0c6ef355"
+        }
+      },
+      "dynamic": "strict",
       "properties": {
+        "application_usage_daily": {
+          "dynamic": "false",
+          "properties": {
+            "timestamp": {
+              "type": "date"
+            }
+          }
+        },
+        "application_usage_totals": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "application_usage_transactional": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "config": {
-          "dynamic": "true",
+          "dynamic": "false",
           "properties": {
             "buildNum": {
               "type": "keyword"
             }
           }
         },
+        "core-usage-stats": {
+          "dynamic": "false",
+          "type": "object"
+        },
+        "coreMigrationVersion": {
+          "type": "keyword"
+        },
         "dashboard": {
-          "dynamic": "strict",
           "properties": {
             "description": {
               "type": "text"
             },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "optionsJSON": {
+              "index": false,
               "type": "text"
             },
             "panelsJSON": {
+              "index": false,
               "type": "text"
             },
             "refreshInterval": {
               "properties": {
                 "display": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "keyword"
                 },
                 "pause": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "boolean"
                 },
                 "section": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 },
                 "value": {
+                  "doc_values": false,
+                  "index": false,
                   "type": "integer"
                 }
               }
             },
             "timeFrom": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "timeRestore": {
+              "doc_values": false,
+              "index": false,
               "type": "boolean"
             },
             "timeTo": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
-            "uiStateJSON": {
-              "type": "text"
-            },
             "version": {
               "type": "integer"
             }
           }
         },
         "index-pattern": {
-          "dynamic": "strict",
+          "dynamic": "false",
           "properties": {
-            "fieldFormatMap": {
-              "type": "text"
-            },
-            "fields": {
+            "title": {
               "type": "text"
             },
-            "intervalName": {
+            "type": {
               "type": "keyword"
+            }
+          }
+        },
+        "kql-telemetry": {
+          "properties": {
+            "optInCount": {
+              "type": "long"
             },
-            "notExpandable": {
+            "optOutCount": {
+              "type": "long"
+            }
+          }
+        },
+        "legacy-url-alias": {
+          "dynamic": "false",
+          "properties": {
+            "disabled": {
               "type": "boolean"
             },
-            "sourceFilters": {
-              "type": "text"
+            "sourceId": {
+              "type": "keyword"
             },
-            "timeFieldName": {
+            "targetType": {
               "type": "keyword"
+            }
+          }
+        },
+        "migrationVersion": {
+          "dynamic": "true",
+          "properties": {
+            "index-pattern": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
             },
-            "title": {
+            "visualization": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            }
+          }
+        },
+        "namespace": {
+          "type": "keyword"
+        },
+        "namespaces": {
+          "type": "keyword"
+        },
+        "originId": {
+          "type": "keyword"
+        },
+        "query": {
+          "properties": {
+            "description": {
               "type": "text"
             },
-            "fieldAttrs": {
+            "filters": {
+              "enabled": false,
+              "type": "object"
+            },
+            "query": {
+              "properties": {
+                "language": {
+                  "type": "keyword"
+                },
+                "query": {
+                  "index": false,
+                  "type": "keyword"
+                }
+              }
+            },
+            "timefilter": {
+              "enabled": false,
+              "type": "object"
+            },
+            "title": {
               "type": "text"
             }
           }
         },
+        "references": {
+          "properties": {
+            "id": {
+              "type": "keyword"
+            },
+            "name": {
+              "type": "keyword"
+            },
+            "type": {
+              "type": "keyword"
+            }
+          },
+          "type": "nested"
+        },
+        "sample-data-telemetry": {
+          "properties": {
+            "installCount": {
+              "type": "long"
+            },
+            "unInstallCount": {
+              "type": "long"
+            }
+          }
+        },
         "search": {
-          "dynamic": "strict",
           "properties": {
             "columns": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "description": {
               "type": "text"
             },
+            "grid": {
+              "enabled": false,
+              "type": "object"
+            },
+            "hideChart": {
+              "doc_values": false,
+              "index": false,
+              "type": "boolean"
+            },
             "hits": {
+              "doc_values": false,
+              "index": false,
               "type": "integer"
             },
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
             "sort": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
@@ -132,16 +310,43 @@
             }
           }
         },
+        "search-telemetry": {
+          "dynamic": "false",
+          "type": "object"
+        },
         "server": {
-          "dynamic": "strict",
+          "dynamic": "false",
+          "type": "object"
+        },
+        "telemetry": {
           "properties": {
-            "uuid": {
+            "allowChangingOptInStatus": {
+              "type": "boolean"
+            },
+            "enabled": {
+              "type": "boolean"
+            },
+            "lastReported": {
+              "type": "date"
+            },
+            "lastVersionChecked": {
               "type": "keyword"
+            },
+            "reportFailureCount": {
+              "type": "integer"
+            },
+            "reportFailureVersion": {
+              "type": "keyword"
+            },
+            "sendUsageFrom": {
+              "type": "keyword"
+            },
+            "userHasSeenNotice": {
+              "type": "boolean"
             }
           }
         },
         "timelion-sheet": {
-          "dynamic": "strict",
           "properties": {
             "description": {
               "type": "text"
@@ -185,8 +390,24 @@
         "type": {
           "type": "keyword"
         },
+        "ui-counter": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
+        "ui-metric": {
+          "properties": {
+            "count": {
+              "type": "integer"
+            }
+          }
+        },
+        "updated_at": {
+          "type": "date"
+        },
         "url": {
-          "dynamic": "strict",
           "properties": {
             "accessCount": {
               "type": "long"
@@ -208,8 +429,15 @@
             }
           }
         },
+        "usage-counters": {
+          "dynamic": "false",
+          "properties": {
+            "domainId": {
+              "type": "keyword"
+            }
+          }
+        },
         "visualization": {
-          "dynamic": "strict",
           "properties": {
             "description": {
               "type": "text"
@@ -217,23 +445,28 @@
             "kibanaSavedObjectMeta": {
               "properties": {
                 "searchSourceJSON": {
+                  "index": false,
                   "type": "text"
                 }
               }
             },
-            "savedSearchId": {
+            "savedSearchRefName": {
+              "doc_values": false,
+              "index": false,
               "type": "keyword"
             },
             "title": {
               "type": "text"
             },
             "uiStateJSON": {
+              "index": false,
               "type": "text"
             },
             "version": {
               "type": "integer"
             },
             "visState": {
+              "index": false,
               "type": "text"
             }
           }
@@ -242,37 +475,13 @@
     },
     "settings": {
       "index": {
-        "number_of_replicas": "1",
-        "number_of_shards": "1"
-      }
-    },
-    "migrationVersion": {
-      "dynamic": "true",
-      "properties": {
-        "index-pattern": {
-          "fields": {
-            "keyword": {
-              "ignore_above": 256,
-              "type": "keyword"
-            }
-          },
-          "type": "text"
-        }
-      }
-    },
-    "references": {
-      "type": "nested",
-      "properties": {
-        "name": {
-          "type": "keyword"
-        },
-        "type": {
-          "type": "keyword"
-        },
-        "id": {
-          "type": "keyword"
-        }
+        "auto_expand_replicas": "0-1",
+        "number_of_replicas": "0",
+        "number_of_shards": "1",
+        "priority": "10",
+        "refresh_interval": "1s",
+        "routing_partition_size": "1"
       }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/x-pack/plugins/alerting/README.md b/x-pack/plugins/alerting/README.md
index cb43e53408090..9d314cc048b70 100644
--- a/x-pack/plugins/alerting/README.md
+++ b/x-pack/plugins/alerting/README.md
@@ -619,7 +619,7 @@ The _registerNavigation_ api allows you to register a handler for a specific ale
 alerting.registerNavigation(
 	'my-application-id',
 	'my-application-id.my-rule-type',
-	(alert: SanitizedAlert, alertType: AlertType) => `/my-unique-rule/${rule.id}`
+	(alert: SanitizedAlert) => `/my-unique-rule/${rule.id}`
 );
 ```
 
@@ -635,7 +635,7 @@ The _registerDefaultNavigation_ API allows you to register a handler for any rul
 ```
 alerting.registerDefaultNavigation(
 	'my-application-id',
-	(alert: SanitizedAlert, alertType: AlertType) => `/my-other-rules/${rule.id}`
+	(alert: SanitizedAlert) => `/my-other-rules/${rule.id}`
 );
 ```
 
diff --git a/x-pack/plugins/alerting/public/alert_navigation_registry/alert_navigation_registry.test.ts b/x-pack/plugins/alerting/public/alert_navigation_registry/alert_navigation_registry.test.ts
index 3364593705301..7eb5996311386 100644
--- a/x-pack/plugins/alerting/public/alert_navigation_registry/alert_navigation_registry.test.ts
+++ b/x-pack/plugins/alerting/public/alert_navigation_registry/alert_navigation_registry.test.ts
@@ -23,7 +23,7 @@ const mockAlertType = (id: string): AlertType => ({
 });
 
 describe('AlertNavigationRegistry', () => {
-  function handler(alert: SanitizedAlert, alertType: AlertType) {
+  function handler(alert: SanitizedAlert) {
     return {};
   }
 
@@ -143,7 +143,7 @@ describe('AlertNavigationRegistry', () => {
     test('returns registered handlers by consumer & Alert Type', () => {
       const registry = new AlertNavigationRegistry();
 
-      function indexThresholdHandler(alert: SanitizedAlert, alertType: AlertType) {
+      function indexThresholdHandler(alert: SanitizedAlert) {
         return {};
       }
 
@@ -155,7 +155,7 @@ describe('AlertNavigationRegistry', () => {
     test('returns default handlers by consumer when there is no handler for requested alert type', () => {
       const registry = new AlertNavigationRegistry();
 
-      function defaultHandler(alert: SanitizedAlert, alertType: AlertType) {
+      function defaultHandler(alert: SanitizedAlert) {
         return {};
       }
 
@@ -168,7 +168,7 @@ describe('AlertNavigationRegistry', () => {
 
       registry.register('siem', mockAlertType('indexThreshold'), () => ({}));
 
-      function defaultHandler(alert: SanitizedAlert, alertType: AlertType) {
+      function defaultHandler(alert: SanitizedAlert) {
         return {};
       }
 
diff --git a/x-pack/plugins/alerting/public/alert_navigation_registry/types.ts b/x-pack/plugins/alerting/public/alert_navigation_registry/types.ts
index bf00d2c1b6eaf..53540facd9652 100644
--- a/x-pack/plugins/alerting/public/alert_navigation_registry/types.ts
+++ b/x-pack/plugins/alerting/public/alert_navigation_registry/types.ts
@@ -6,9 +6,15 @@
  */
 
 import { JsonObject } from '../../../../../src/plugins/kibana_utils/common';
-import { AlertType, SanitizedAlert } from '../../common';
+import { SanitizedAlert } from '../../common';
 
-export type AlertNavigationHandler = (
-  alert: SanitizedAlert,
-  alertType: AlertType
-) => JsonObject | string;
+/**
+ * Returns information that can be used to navigate to a specific page to view the given rule.
+ *
+ * @param rule The rule to view
+ * @returns A URL that is meant to be relative to your application id, or a state object that your application uses to render
+ * the rule. This information is intended to be used with cores NavigateToApp function, along with the application id that was
+ * originally registered to {@link PluginSetupContract.registerNavigation}.
+ *
+ */
+export type AlertNavigationHandler = (alert: SanitizedAlert) => JsonObject | string;
diff --git a/x-pack/plugins/alerting/public/index.ts b/x-pack/plugins/alerting/public/index.ts
index 5edca2f8c4c41..7c61ea1b6b1fd 100644
--- a/x-pack/plugins/alerting/public/index.ts
+++ b/x-pack/plugins/alerting/public/index.ts
@@ -6,7 +6,8 @@
  */
 
 import { AlertingPublicPlugin } from './plugin';
-export { PluginSetupContract, PluginStartContract } from './plugin';
+export type { PluginSetupContract, PluginStartContract } from './plugin';
+export type { AlertNavigationHandler } from './alert_navigation_registry';
 
 export function plugin() {
   return new AlertingPublicPlugin();
diff --git a/x-pack/plugins/alerting/public/plugin.ts b/x-pack/plugins/alerting/public/plugin.ts
index 025467d92a6ac..be7080f5df6da 100644
--- a/x-pack/plugins/alerting/public/plugin.ts
+++ b/x-pack/plugins/alerting/public/plugin.ts
@@ -12,12 +12,38 @@ import { loadAlert, loadAlertType } from './alert_api';
 import { Alert, AlertNavigation } from '../common';
 
 export interface PluginSetupContract {
+  /**
+   * Register a customized view of the particular rule type. Stack Management provides a generic overview, but a developer can register a
+   * custom navigation to provide the user an extra link to a more curated view. The alerting plugin doesn't actually do
+   * anything with this information, but it can be used by other plugins via the `getNavigation` functionality. Currently
+   * the trigger_actions_ui plugin uses it to expose the link from the generic rule details view in Stack Management.
+   *
+   * @param applicationId The application id that the user should be navigated to, to view a particular alert in a custom way.
+   * @param ruleType The rule type that has been registered with Alerting.Server.PluginSetupContract.registerType. If
+   * no such rule with that id exists, a warning is output to the console log. It used to throw an error, but that was temporarily moved
+   * because it was causing flaky test failures with https://github.com/elastic/kibana/issues/59229 and needs to be
+   * investigated more.
+   * @param handler The navigation handler should return either a relative URL, or a state object. This information can be used,
+   * in conjunction with the consumer id, to navigate the user to a custom URL to view a rule's details.
+   * @throws an error if the given applicationId and ruleType combination has already been registered.
+   */
   registerNavigation: (
-    consumer: string,
-    alertType: string,
+    applicationId: string,
+    ruleType: string,
     handler: AlertNavigationHandler
   ) => void;
-  registerDefaultNavigation: (consumer: string, handler: AlertNavigationHandler) => void;
+
+  /**
+   * Register a customized view for all rule types with this application id. Stack Management provides a generic overview, but a developer can register a
+   * custom navigation to provide the user an extra link to a more curated view. The alerting plugin doesn't actually do
+   * anything with this information, but it can be used by other plugins via the `getNavigation` functionality. Currently
+   * the trigger_actions_ui plugin uses it to expose the link from the generic rule details view in Stack Management.
+   *
+   * @param applicationId The application id that the user should be navigated to, to view a particular alert in a custom way.
+   * @param handler The navigation handler should return either a relative URL, or a state object. This information can be used,
+   * in conjunction with the consumer id, to navigate the user to a custom URL to view a rule's details.
+   */
+  registerDefaultNavigation: (applicationId: string, handler: AlertNavigationHandler) => void;
 }
 export interface PluginStartContract {
   getNavigation: (alertId: Alert['id']) => Promise<AlertNavigation | undefined>;
@@ -29,23 +55,25 @@ export class AlertingPublicPlugin implements Plugin<PluginSetupContract, PluginS
     this.alertNavigationRegistry = new AlertNavigationRegistry();
 
     const registerNavigation = async (
-      consumer: string,
-      alertTypeId: string,
+      applicationId: string,
+      ruleTypeId: string,
       handler: AlertNavigationHandler
     ) => {
-      const alertType = await loadAlertType({ http: core.http, id: alertTypeId });
+      const alertType = await loadAlertType({ http: core.http, id: ruleTypeId });
       if (!alertType) {
         // eslint-disable-next-line no-console
         console.log(
-          `Unable to register navigation for alert type "${alertTypeId}" because it is not registered on the server side.`
+          `Unable to register navigation for rule type "${ruleTypeId}" because it is not registered on the server side.`
         );
         return;
       }
-      this.alertNavigationRegistry!.register(consumer, alertType, handler);
+      this.alertNavigationRegistry!.register(applicationId, alertType, handler);
     };
 
-    const registerDefaultNavigation = async (consumer: string, handler: AlertNavigationHandler) =>
-      this.alertNavigationRegistry!.registerDefault(consumer, handler);
+    const registerDefaultNavigation = async (
+      applicationId: string,
+      handler: AlertNavigationHandler
+    ) => this.alertNavigationRegistry!.registerDefault(applicationId, handler);
 
     return {
       registerNavigation,
@@ -69,7 +97,7 @@ export class AlertingPublicPlugin implements Plugin<PluginSetupContract, PluginS
 
         if (this.alertNavigationRegistry!.has(alert.consumer, alertType)) {
           const navigationHandler = this.alertNavigationRegistry!.get(alert.consumer, alertType);
-          const state = navigationHandler(alert, alertType);
+          const state = navigationHandler(alert);
           return typeof state === 'string' ? { path: state } : { state };
         }
       },
diff --git a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts
index 5ab25fbfa39e7..25f0656163f5d 100644
--- a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts
+++ b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts
@@ -67,7 +67,7 @@ const createExecutionHandlerParams: jest.Mocked<
   >
 > = {
   actionsPlugin: mockActionsPlugin,
-  spaceId: 'default',
+  spaceId: 'test1',
   alertId: '1',
   alertName: 'name-of-alert',
   tags: ['tag-A', 'tag-B'],
@@ -130,7 +130,7 @@ test('enqueues execution per selected action', async () => {
         "apiKey": "MTIzOmFiYw==",
         "id": "1",
         "params": Object {
-          "alertVal": "My 1 name-of-alert default tag-A,tag-B 2 goes here",
+          "alertVal": "My 1 name-of-alert test1 tag-A,tag-B 2 goes here",
           "contextVal": "My  goes here",
           "foo": true,
           "stateVal": "My  goes here",
@@ -142,7 +142,7 @@ test('enqueues execution per selected action', async () => {
           },
           "type": "SAVED_OBJECT",
         },
-        "spaceId": "default",
+        "spaceId": "test1",
       },
     ]
   `);
@@ -154,6 +154,10 @@ test('enqueues execution per selected action', async () => {
         Object {
           "event": Object {
             "action": "execute-action",
+            "category": Array [
+              "alerts",
+            ],
+            "kind": "alert",
           },
           "kibana": Object {
             "alerting": Object {
@@ -164,18 +168,28 @@ test('enqueues execution per selected action', async () => {
             "saved_objects": Array [
               Object {
                 "id": "1",
+                "namespace": "test1",
                 "rel": "primary",
                 "type": "alert",
                 "type_id": "test",
               },
               Object {
                 "id": "1",
+                "namespace": "test1",
                 "type": "action",
                 "type_id": "test",
               },
             ],
           },
           "message": "alert: test:1: 'name-of-alert' instanceId: '2' scheduled actionGroup: 'default' action: test:1",
+          "rule": Object {
+            "category": "test",
+            "id": "1",
+            "license": "basic",
+            "name": "name-of-alert",
+            "namespace": "test1",
+            "ruleset": "alerts",
+          },
         },
       ],
     ]
@@ -183,10 +197,10 @@ test('enqueues execution per selected action', async () => {
 
   expect(jest.requireMock('./inject_action_params').injectActionParams).toHaveBeenCalledWith({
     ruleId: '1',
-    spaceId: 'default',
+    spaceId: 'test1',
     actionTypeId: 'test',
     actionParams: {
-      alertVal: 'My 1 name-of-alert default tag-A,tag-B 2 goes here',
+      alertVal: 'My 1 name-of-alert test1 tag-A,tag-B 2 goes here',
       contextVal: 'My  goes here',
       foo: true,
       stateVal: 'My  goes here',
@@ -233,7 +247,7 @@ test(`doesn't call actionsPlugin.execute for disabled actionTypes`, async () =>
       id: '1',
       type: 'alert',
     }),
-    spaceId: 'default',
+    spaceId: 'test1',
     apiKey: createExecutionHandlerParams.apiKey,
   });
 });
@@ -308,7 +322,7 @@ test('context attribute gets parameterized', async () => {
         "apiKey": "MTIzOmFiYw==",
         "id": "1",
         "params": Object {
-          "alertVal": "My 1 name-of-alert default tag-A,tag-B 2 goes here",
+          "alertVal": "My 1 name-of-alert test1 tag-A,tag-B 2 goes here",
           "contextVal": "My context-val goes here",
           "foo": true,
           "stateVal": "My  goes here",
@@ -320,7 +334,7 @@ test('context attribute gets parameterized', async () => {
           },
           "type": "SAVED_OBJECT",
         },
-        "spaceId": "default",
+        "spaceId": "test1",
       },
     ]
   `);
@@ -341,7 +355,7 @@ test('state attribute gets parameterized', async () => {
         "apiKey": "MTIzOmFiYw==",
         "id": "1",
         "params": Object {
-          "alertVal": "My 1 name-of-alert default tag-A,tag-B 2 goes here",
+          "alertVal": "My 1 name-of-alert test1 tag-A,tag-B 2 goes here",
           "contextVal": "My  goes here",
           "foo": true,
           "stateVal": "My state-val goes here",
@@ -353,7 +367,7 @@ test('state attribute gets parameterized', async () => {
           },
           "type": "SAVED_OBJECT",
         },
-        "spaceId": "default",
+        "spaceId": "test1",
       },
     ]
   `);
diff --git a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts
index ef93179bdaba1..c3a36297c217a 100644
--- a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts
+++ b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts
@@ -174,7 +174,11 @@ export function createExecutionHandler<
       const namespace = spaceId === 'default' ? {} : { namespace: spaceId };
 
       const event: IEvent = {
-        event: { action: EVENT_LOG_ACTIONS.executeAction },
+        event: {
+          action: EVENT_LOG_ACTIONS.executeAction,
+          kind: 'alert',
+          category: [alertType.producer],
+        },
         kibana: {
           alerting: {
             instance_id: alertInstanceId,
@@ -192,6 +196,14 @@ export function createExecutionHandler<
             { type: 'action', id: action.id, type_id: action.actionTypeId, ...namespace },
           ],
         },
+        rule: {
+          id: alertId,
+          license: alertType.minimumLicenseRequired,
+          category: alertType.id,
+          ruleset: alertType.producer,
+          ...namespace,
+          name: alertName,
+        },
       };
 
       event.message = `alert: ${alertLabel} instanceId: '${alertInstanceId}' scheduled ${
diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts
index 6847b17bcef4b..4893e509f6b6a 100644
--- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts
+++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts
@@ -266,6 +266,10 @@ describe('Task Runner', () => {
         "@timestamp": "1970-01-01T00:00:00.000Z",
         "event": Object {
           "action": "execute",
+          "category": Array [
+            "alerts",
+          ],
+          "kind": "alert",
           "outcome": "success",
         },
         "kibana": Object {
@@ -283,6 +287,14 @@ describe('Task Runner', () => {
           ],
         },
         "message": "alert executed: test:1: 'alert-name'",
+        "rule": Object {
+          "category": "test",
+          "id": "1",
+          "license": "basic",
+          "name": "alert-name",
+          "namespace": undefined,
+          "ruleset": "alerts",
+        },
       }
     `);
 
@@ -373,6 +385,8 @@ describe('Task Runner', () => {
     expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, {
       event: {
         action: 'new-instance',
+        category: ['alerts'],
+        kind: 'alert',
         duration: 0,
         start: '1970-01-01T00:00:00.000Z',
       },
@@ -393,35 +407,45 @@ describe('Task Runner', () => {
         ],
       },
       message: "test:1: 'alert-name' created new instance: '1'",
+      rule: {
+        category: 'test',
+        id: '1',
+        license: 'basic',
+        name: 'alert-name',
+        namespace: undefined,
+        ruleset: 'alerts',
+      },
     });
     expect(eventLogger.logEvent).toHaveBeenNthCalledWith(2, {
       event: {
         action: 'active-instance',
+        category: ['alerts'],
         duration: 0,
+        kind: 'alert',
         start: '1970-01-01T00:00:00.000Z',
       },
       kibana: {
-        alerting: {
-          instance_id: '1',
-          action_group_id: 'default',
-          action_subgroup: 'subDefault',
-        },
+        alerting: { action_group_id: 'default', action_subgroup: 'subDefault', instance_id: '1' },
         saved_objects: [
-          {
-            id: '1',
-            namespace: undefined,
-            rel: 'primary',
-            type: 'alert',
-            type_id: 'test',
-          },
+          { id: '1', namespace: undefined, rel: 'primary', type: 'alert', type_id: 'test' },
         ],
       },
       message:
         "test:1: 'alert-name' active instance: '1' in actionGroup(subgroup): 'default(subDefault)'",
+      rule: {
+        category: 'test',
+        id: '1',
+        license: 'basic',
+        name: 'alert-name',
+        namespace: undefined,
+        ruleset: 'alerts',
+      },
     });
     expect(eventLogger.logEvent).toHaveBeenNthCalledWith(3, {
       event: {
         action: 'execute-action',
+        category: ['alerts'],
+        kind: 'alert',
       },
       kibana: {
         alerting: {
@@ -447,13 +471,18 @@ describe('Task Runner', () => {
       },
       message:
         "alert: test:1: 'alert-name' instanceId: '1' scheduled actionGroup(subgroup): 'default(subDefault)' action: action:1",
+      rule: {
+        category: 'test',
+        id: '1',
+        license: 'basic',
+        name: 'alert-name',
+        namespace: undefined,
+        ruleset: 'alerts',
+      },
     });
     expect(eventLogger.logEvent).toHaveBeenNthCalledWith(4, {
       '@timestamp': '1970-01-01T00:00:00.000Z',
-      event: {
-        action: 'execute',
-        outcome: 'success',
-      },
+      event: { action: 'execute', category: ['alerts'], kind: 'alert', outcome: 'success' },
       kibana: {
         alerting: {
           status: 'active',
@@ -469,6 +498,14 @@ describe('Task Runner', () => {
         ],
       },
       message: "alert executed: test:1: 'alert-name'",
+      rule: {
+        category: 'test',
+        id: '1',
+        license: 'basic',
+        name: 'alert-name',
+        namespace: undefined,
+        ruleset: 'alerts',
+      },
     });
   });
 
@@ -529,6 +566,8 @@ describe('Task Runner', () => {
     expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, {
       event: {
         action: 'new-instance',
+        category: ['alerts'],
+        kind: 'alert',
         duration: 0,
         start: '1970-01-01T00:00:00.000Z',
       },
@@ -548,10 +587,20 @@ describe('Task Runner', () => {
         ],
       },
       message: "test:1: 'alert-name' created new instance: '1'",
+      rule: {
+        category: 'test',
+        id: '1',
+        license: 'basic',
+        name: 'alert-name',
+        namespace: undefined,
+        ruleset: 'alerts',
+      },
     });
     expect(eventLogger.logEvent).toHaveBeenNthCalledWith(2, {
       event: {
         action: 'active-instance',
+        category: ['alerts'],
+        kind: 'alert',
         duration: 0,
         start: '1970-01-01T00:00:00.000Z',
       },
@@ -571,11 +620,21 @@ describe('Task Runner', () => {
         ],
       },
       message: "test:1: 'alert-name' active instance: '1' in actionGroup: 'default'",
+      rule: {
+        category: 'test',
+        id: '1',
+        license: 'basic',
+        name: 'alert-name',
+        namespace: undefined,
+        ruleset: 'alerts',
+      },
     });
     expect(eventLogger.logEvent).toHaveBeenNthCalledWith(3, {
       '@timestamp': '1970-01-01T00:00:00.000Z',
       event: {
         action: 'execute',
+        category: ['alerts'],
+        kind: 'alert',
         outcome: 'success',
       },
       kibana: {
@@ -593,6 +652,14 @@ describe('Task Runner', () => {
         ],
       },
       message: "alert executed: test:1: 'alert-name'",
+      rule: {
+        category: 'test',
+        id: '1',
+        license: 'basic',
+        name: 'alert-name',
+        namespace: undefined,
+        ruleset: 'alerts',
+      },
     });
   });
 
@@ -711,7 +778,11 @@ describe('Task Runner', () => {
           Object {
             "event": Object {
               "action": "active-instance",
+              "category": Array [
+                "alerts",
+              ],
               "duration": 86400000000000,
+              "kind": "alert",
               "start": "1969-12-31T00:00:00.000Z",
             },
             "kibana": Object {
@@ -730,6 +801,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' active instance: '1' in actionGroup: 'default'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
@@ -737,6 +816,10 @@ describe('Task Runner', () => {
             "@timestamp": "1970-01-01T00:00:00.000Z",
             "event": Object {
               "action": "execute",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
               "outcome": "success",
             },
             "kibana": Object {
@@ -754,6 +837,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "alert executed: test:1: 'alert-name'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
       ]
@@ -944,7 +1035,11 @@ describe('Task Runner', () => {
         Object {
           "event": Object {
             "action": "new-instance",
+            "category": Array [
+              "alerts",
+            ],
             "duration": 0,
+            "kind": "alert",
             "start": "1970-01-01T00:00:00.000Z",
           },
           "kibana": Object {
@@ -963,13 +1058,25 @@ describe('Task Runner', () => {
             ],
           },
           "message": "test:1: 'alert-name' created new instance: '1'",
+          "rule": Object {
+            "category": "test",
+            "id": "1",
+            "license": "basic",
+            "name": "alert-name",
+            "namespace": undefined,
+            "ruleset": "alerts",
+          },
         },
       ],
       Array [
         Object {
           "event": Object {
             "action": "active-instance",
+            "category": Array [
+              "alerts",
+            ],
             "duration": 0,
+            "kind": "alert",
             "start": "1970-01-01T00:00:00.000Z",
           },
           "kibana": Object {
@@ -988,12 +1095,24 @@ describe('Task Runner', () => {
             ],
           },
           "message": "test:1: 'alert-name' active instance: '1' in actionGroup: 'default'",
+          "rule": Object {
+            "category": "test",
+            "id": "1",
+            "license": "basic",
+            "name": "alert-name",
+            "namespace": undefined,
+            "ruleset": "alerts",
+          },
         },
       ],
       Array [
         Object {
           "event": Object {
             "action": "execute-action",
+            "category": Array [
+              "alerts",
+            ],
+            "kind": "alert",
           },
           "kibana": Object {
             "alerting": Object {
@@ -1018,6 +1137,14 @@ describe('Task Runner', () => {
             ],
           },
           "message": "alert: test:1: 'alert-name' instanceId: '1' scheduled actionGroup: 'default' action: action:1",
+          "rule": Object {
+            "category": "test",
+            "id": "1",
+            "license": "basic",
+            "name": "alert-name",
+            "namespace": undefined,
+            "ruleset": "alerts",
+          },
         },
       ],
       Array [
@@ -1025,6 +1152,10 @@ describe('Task Runner', () => {
           "@timestamp": "1970-01-01T00:00:00.000Z",
           "event": Object {
             "action": "execute",
+            "category": Array [
+              "alerts",
+            ],
+            "kind": "alert",
             "outcome": "success",
           },
           "kibana": Object {
@@ -1042,6 +1173,14 @@ describe('Task Runner', () => {
             ],
           },
           "message": "alert executed: test:1: 'alert-name'",
+          "rule": Object {
+            "category": "test",
+            "id": "1",
+            "license": "basic",
+            "name": "alert-name",
+            "namespace": undefined,
+            "ruleset": "alerts",
+          },
         },
       ],
     ]
@@ -1146,8 +1285,12 @@ describe('Task Runner', () => {
           Object {
             "event": Object {
               "action": "recovered-instance",
+              "category": Array [
+                "alerts",
+              ],
               "duration": 64800000000000,
               "end": "1970-01-01T00:00:00.000Z",
+              "kind": "alert",
               "start": "1969-12-31T06:00:00.000Z",
             },
             "kibana": Object {
@@ -1165,13 +1308,25 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' instance '2' has recovered",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
           Object {
             "event": Object {
               "action": "active-instance",
+              "category": Array [
+                "alerts",
+              ],
               "duration": 86400000000000,
+              "kind": "alert",
               "start": "1969-12-31T00:00:00.000Z",
             },
             "kibana": Object {
@@ -1190,12 +1345,24 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' active instance: '1' in actionGroup: 'default'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
           Object {
             "event": Object {
               "action": "execute-action",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
             },
             "kibana": Object {
               "alerting": Object {
@@ -1220,12 +1387,24 @@ describe('Task Runner', () => {
               ],
             },
             "message": "alert: test:1: 'alert-name' instanceId: '2' scheduled actionGroup: 'recovered' action: action:2",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
           Object {
             "event": Object {
               "action": "execute-action",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
             },
             "kibana": Object {
               "alerting": Object {
@@ -1250,6 +1429,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "alert: test:1: 'alert-name' instanceId: '1' scheduled actionGroup: 'default' action: action:1",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
@@ -1257,6 +1444,10 @@ describe('Task Runner', () => {
             "@timestamp": "1970-01-01T00:00:00.000Z",
             "event": Object {
               "action": "execute",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
               "outcome": "success",
             },
             "kibana": Object {
@@ -1274,6 +1465,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "alert executed: test:1: 'alert-name'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
       ]
@@ -1573,8 +1772,12 @@ describe('Task Runner', () => {
           Object {
             "event": Object {
               "action": "recovered-instance",
+              "category": Array [
+                "alerts",
+              ],
               "duration": 64800000000000,
               "end": "1970-01-01T00:00:00.000Z",
+              "kind": "alert",
               "start": "1969-12-31T06:00:00.000Z",
             },
             "kibana": Object {
@@ -1593,13 +1796,25 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' instance '2' has recovered",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
           Object {
             "event": Object {
               "action": "active-instance",
+              "category": Array [
+                "alerts",
+              ],
               "duration": 86400000000000,
+              "kind": "alert",
               "start": "1969-12-31T00:00:00.000Z",
             },
             "kibana": Object {
@@ -1618,6 +1833,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' active instance: '1' in actionGroup: 'default'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
@@ -1625,6 +1848,10 @@ describe('Task Runner', () => {
             "@timestamp": "1970-01-01T00:00:00.000Z",
             "event": Object {
               "action": "execute",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
               "outcome": "success",
             },
             "kibana": Object {
@@ -1642,6 +1869,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "alert executed: test:1: 'alert-name'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
       ]
@@ -1835,6 +2070,10 @@ describe('Task Runner', () => {
             },
             "event": Object {
               "action": "execute",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
               "outcome": "failure",
               "reason": "execute",
             },
@@ -1853,6 +2092,13 @@ describe('Task Runner', () => {
               ],
             },
             "message": "alert execution failure: test:1: 'alert-name'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
       ]
@@ -1895,6 +2141,10 @@ describe('Task Runner', () => {
             },
             "event": Object {
               "action": "execute",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
               "outcome": "failure",
               "reason": "decrypt",
             },
@@ -1913,6 +2163,13 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: execution failed",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
       ]
@@ -1963,6 +2220,10 @@ describe('Task Runner', () => {
             },
             "event": Object {
               "action": "execute",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
               "outcome": "failure",
               "reason": "license",
             },
@@ -1981,6 +2242,13 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: execution failed",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
       ]
@@ -2031,6 +2299,10 @@ describe('Task Runner', () => {
             },
             "event": Object {
               "action": "execute",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
               "outcome": "failure",
               "reason": "unknown",
             },
@@ -2049,6 +2321,13 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: execution failed",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
       ]
@@ -2098,6 +2377,10 @@ describe('Task Runner', () => {
             },
             "event": Object {
               "action": "execute",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
               "outcome": "failure",
               "reason": "read",
             },
@@ -2116,6 +2399,13 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: execution failed",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
       ]
@@ -2329,7 +2619,11 @@ describe('Task Runner', () => {
           Object {
             "event": Object {
               "action": "new-instance",
+              "category": Array [
+                "alerts",
+              ],
               "duration": 0,
+              "kind": "alert",
               "start": "1970-01-01T00:00:00.000Z",
             },
             "kibana": Object {
@@ -2348,13 +2642,25 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' created new instance: '1'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
           Object {
             "event": Object {
               "action": "new-instance",
+              "category": Array [
+                "alerts",
+              ],
               "duration": 0,
+              "kind": "alert",
               "start": "1970-01-01T00:00:00.000Z",
             },
             "kibana": Object {
@@ -2373,13 +2679,25 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' created new instance: '2'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
           Object {
             "event": Object {
               "action": "active-instance",
+              "category": Array [
+                "alerts",
+              ],
               "duration": 0,
+              "kind": "alert",
               "start": "1970-01-01T00:00:00.000Z",
             },
             "kibana": Object {
@@ -2398,13 +2716,25 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' active instance: '1' in actionGroup: 'default'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
           Object {
             "event": Object {
               "action": "active-instance",
+              "category": Array [
+                "alerts",
+              ],
               "duration": 0,
+              "kind": "alert",
               "start": "1970-01-01T00:00:00.000Z",
             },
             "kibana": Object {
@@ -2423,6 +2753,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' active instance: '2' in actionGroup: 'default'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
@@ -2430,6 +2768,10 @@ describe('Task Runner', () => {
             "@timestamp": "1970-01-01T00:00:00.000Z",
             "event": Object {
               "action": "execute",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
               "outcome": "success",
             },
             "kibana": Object {
@@ -2447,6 +2789,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "alert executed: test:1: 'alert-name'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
       ]
@@ -2521,7 +2871,11 @@ describe('Task Runner', () => {
           Object {
             "event": Object {
               "action": "active-instance",
+              "category": Array [
+                "alerts",
+              ],
               "duration": 86400000000000,
+              "kind": "alert",
               "start": "1969-12-31T00:00:00.000Z",
             },
             "kibana": Object {
@@ -2540,13 +2894,25 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' active instance: '1' in actionGroup: 'default'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
           Object {
             "event": Object {
               "action": "active-instance",
+              "category": Array [
+                "alerts",
+              ],
               "duration": 64800000000000,
+              "kind": "alert",
               "start": "1969-12-31T06:00:00.000Z",
             },
             "kibana": Object {
@@ -2565,6 +2931,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' active instance: '2' in actionGroup: 'default'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
@@ -2572,6 +2946,10 @@ describe('Task Runner', () => {
             "@timestamp": "1970-01-01T00:00:00.000Z",
             "event": Object {
               "action": "execute",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
               "outcome": "success",
             },
             "kibana": Object {
@@ -2589,6 +2967,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "alert executed: test:1: 'alert-name'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
       ]
@@ -2655,6 +3041,10 @@ describe('Task Runner', () => {
           Object {
             "event": Object {
               "action": "active-instance",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
             },
             "kibana": Object {
               "alerting": Object {
@@ -2672,12 +3062,24 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' active instance: '1' in actionGroup: 'default'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
           Object {
             "event": Object {
               "action": "active-instance",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
             },
             "kibana": Object {
               "alerting": Object {
@@ -2695,6 +3097,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' active instance: '2' in actionGroup: 'default'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
@@ -2702,6 +3112,10 @@ describe('Task Runner', () => {
             "@timestamp": "1970-01-01T00:00:00.000Z",
             "event": Object {
               "action": "execute",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
               "outcome": "success",
             },
             "kibana": Object {
@@ -2719,6 +3133,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "alert executed: test:1: 'alert-name'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
       ]
@@ -2780,8 +3202,12 @@ describe('Task Runner', () => {
           Object {
             "event": Object {
               "action": "recovered-instance",
+              "category": Array [
+                "alerts",
+              ],
               "duration": 86400000000000,
               "end": "1970-01-01T00:00:00.000Z",
+              "kind": "alert",
               "start": "1969-12-31T00:00:00.000Z",
             },
             "kibana": Object {
@@ -2799,14 +3225,26 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' instance '1' has recovered",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
           Object {
             "event": Object {
               "action": "recovered-instance",
+              "category": Array [
+                "alerts",
+              ],
               "duration": 64800000000000,
               "end": "1970-01-01T00:00:00.000Z",
+              "kind": "alert",
               "start": "1969-12-31T06:00:00.000Z",
             },
             "kibana": Object {
@@ -2824,6 +3262,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' instance '2' has recovered",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
@@ -2831,6 +3277,10 @@ describe('Task Runner', () => {
             "@timestamp": "1970-01-01T00:00:00.000Z",
             "event": Object {
               "action": "execute",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
               "outcome": "success",
             },
             "kibana": Object {
@@ -2848,6 +3298,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "alert executed: test:1: 'alert-name'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
       ]
@@ -2911,6 +3369,10 @@ describe('Task Runner', () => {
           Object {
             "event": Object {
               "action": "recovered-instance",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
             },
             "kibana": Object {
               "alerting": Object {
@@ -2927,12 +3389,24 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' instance '1' has recovered",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
           Object {
             "event": Object {
               "action": "recovered-instance",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
             },
             "kibana": Object {
               "alerting": Object {
@@ -2949,6 +3423,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "test:1: 'alert-name' instance '2' has recovered",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
         Array [
@@ -2956,6 +3438,10 @@ describe('Task Runner', () => {
             "@timestamp": "1970-01-01T00:00:00.000Z",
             "event": Object {
               "action": "execute",
+              "category": Array [
+                "alerts",
+              ],
+              "kind": "alert",
               "outcome": "success",
             },
             "kibana": Object {
@@ -2973,6 +3459,14 @@ describe('Task Runner', () => {
               ],
             },
             "message": "alert executed: test:1: 'alert-name'",
+            "rule": Object {
+              "category": "test",
+              "id": "1",
+              "license": "basic",
+              "name": "alert-name",
+              "namespace": undefined,
+              "ruleset": "alerts",
+            },
           },
         ],
       ]
diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts
index 4a214efceaa7d..c9ca5d85e5116 100644
--- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts
+++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts
@@ -303,6 +303,10 @@ export class TaskRunner<
     event.message = `alert executed: ${alertLabel}`;
     event.event = event.event || {};
     event.event.outcome = 'success';
+    event.rule = {
+      ...event.rule,
+      name: alert.name,
+    };
 
     // Cleanup alert instances that are no longer scheduling actions to avoid over populating the alertInstances object
     const instancesWithScheduledActions = pickBy(
@@ -337,7 +341,8 @@ export class TaskRunner<
       alertId,
       alertLabel,
       namespace,
-      ruleTypeId: alert.alertTypeId,
+      ruleType: alertType,
+      rule: alert,
     });
 
     if (!muteAll) {
@@ -493,7 +498,11 @@ export class TaskRunner<
       // explicitly set execute timestamp so it will be before other events
       // generated here (new-instance, schedule-action, etc)
       '@timestamp': runDate,
-      event: { action: EVENT_LOG_ACTIONS.execute },
+      event: {
+        action: EVENT_LOG_ACTIONS.execute,
+        kind: 'alert',
+        category: [this.alertType.producer],
+      },
       kibana: {
         saved_objects: [
           {
@@ -505,6 +514,13 @@ export class TaskRunner<
           },
         ],
       },
+      rule: {
+        id: alertId,
+        license: this.alertType.minimumLicenseRequired,
+        category: this.alertType.id,
+        ruleset: this.alertType.producer,
+        namespace,
+      },
     };
     eventLogger.startTiming(event);
 
@@ -665,7 +681,19 @@ interface GenerateNewAndRecoveredInstanceEventsParams<
   alertId: string;
   alertLabel: string;
   namespace: string | undefined;
-  ruleTypeId: string;
+  ruleType: NormalizedAlertType<
+    AlertTypeParams,
+    AlertTypeState,
+    {
+      [x: string]: unknown;
+    },
+    {
+      [x: string]: unknown;
+    },
+    string,
+    string
+  >;
+  rule: SanitizedAlert<AlertTypeParams>;
 }
 
 function generateNewAndRecoveredInstanceEvents<
@@ -679,7 +707,8 @@ function generateNewAndRecoveredInstanceEvents<
     currentAlertInstances,
     originalAlertInstances,
     recoveredAlertInstances,
-    ruleTypeId,
+    rule,
+    ruleType,
   } = params;
   const originalAlertInstanceIds = Object.keys(originalAlertInstances);
   const currentAlertInstanceIds = Object.keys(currentAlertInstances);
@@ -746,6 +775,8 @@ function generateNewAndRecoveredInstanceEvents<
     const event: IEvent = {
       event: {
         action,
+        kind: 'alert',
+        category: [ruleType.producer],
         ...(state?.start ? { start: state.start as string } : {}),
         ...(state?.end ? { end: state.end as string } : {}),
         ...(state?.duration !== undefined ? { duration: state.duration as number } : {}),
@@ -761,12 +792,20 @@ function generateNewAndRecoveredInstanceEvents<
             rel: SAVED_OBJECT_REL_PRIMARY,
             type: 'alert',
             id: alertId,
-            type_id: ruleTypeId,
+            type_id: ruleType.id,
             namespace,
           },
         ],
       },
       message,
+      rule: {
+        id: rule.id,
+        license: ruleType.minimumLicenseRequired,
+        category: ruleType.id,
+        ruleset: ruleType.producer,
+        namespace,
+        name: rule.name,
+      },
     };
     eventLogger.logEvent(event);
   }
diff --git a/x-pack/plugins/apm/server/lib/fleet/register_fleet_policy_callbacks.ts b/x-pack/plugins/apm/server/lib/fleet/register_fleet_policy_callbacks.ts
index e4306b4c2ec98..35c7f0dfdfd73 100644
--- a/x-pack/plugins/apm/server/lib/fleet/register_fleet_policy_callbacks.ts
+++ b/x-pack/plugins/apm/server/lib/fleet/register_fleet_policy_callbacks.ts
@@ -115,6 +115,7 @@ export function getPackagePolicyWithAgentConfigurations(
       {
         ...firstInput,
         config: {
+          ...firstInput.config,
           [APM_SERVER]: {
             value: {
               ...apmServerValue,
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.test.js
index fc5d03190d4f8..adee8a56dea49 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.test.js
+++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.test.js
@@ -6,11 +6,17 @@
  */
 
 import { of } from 'rxjs';
+import { TestScheduler } from 'rxjs/testing';
 import { functionWrapper } from '../../../test_helpers/function_wrapper';
 import { caseFn } from './case';
 
 describe('case', () => {
   const fn = functionWrapper(caseFn);
+  let testScheduler;
+
+  beforeEach(() => {
+    testScheduler = new TestScheduler((actual, expected) => expect(actual).toStrictEqual(expected));
+  });
 
   describe('spec', () => {
     it('is a function', () => {
@@ -19,29 +25,22 @@ describe('case', () => {
   });
 
   describe('function', () => {
-    describe('no args', () => {
-      it('should return a case object that matches with the result as the context', () => {
-        const context = null;
-        const args = {};
-        expect(fn(context, args)).resolves.toEqual({
-          type: 'case',
-          matches: true,
-          result: context,
-        });
-      });
-    });
-
     describe('no if or value', () => {
       it('should return the result if provided', () => {
         const context = null;
         const args = {
           then: () => of('foo'),
         };
-        expect(fn(context, args)).resolves.toEqual({
-          type: 'case',
-          matches: true,
-          result: 'foo',
-        });
+
+        testScheduler.run(({ expectObservable }) =>
+          expectObservable(fn(context, args)).toBe('(0|)', [
+            {
+              type: 'case',
+              matches: true,
+              result: 'foo',
+            },
+          ])
+        );
       });
     });
 
@@ -49,11 +48,16 @@ describe('case', () => {
       it('should return as the matches prop', () => {
         const context = null;
         const args = { if: false };
-        expect(fn(context, args)).resolves.toEqual({
-          type: 'case',
-          matches: args.if,
-          result: context,
-        });
+
+        testScheduler.run(({ expectObservable }) =>
+          expectObservable(fn(context, args)).toBe('(0|)', [
+            {
+              type: 'case',
+              matches: args.if,
+              result: context,
+            },
+          ])
+        );
       });
     });
 
@@ -63,15 +67,23 @@ describe('case', () => {
           when: () => of('foo'),
           then: () => of('bar'),
         };
-        expect(fn('foo', args)).resolves.toEqual({
-          type: 'case',
-          matches: true,
-          result: 'bar',
-        });
-        expect(fn('bar', args)).resolves.toEqual({
-          type: 'case',
-          matches: false,
-          result: null,
+
+        testScheduler.run(({ expectObservable }) => {
+          expectObservable(fn('foo', args)).toBe('(0|)', [
+            {
+              type: 'case',
+              matches: true,
+              result: 'bar',
+            },
+          ]);
+
+          expectObservable(fn('bar', args)).toBe('(0|)', [
+            {
+              type: 'case',
+              matches: false,
+              result: null,
+            },
+          ]);
         });
       });
     });
@@ -81,13 +93,18 @@ describe('case', () => {
         const context = null;
         const args = {
           when: () => 'foo',
-          if: true,
+          if: false,
         };
-        expect(fn(context, args)).resolves.toEqual({
-          type: 'case',
-          matches: args.if,
-          result: context,
-        });
+
+        testScheduler.run(({ expectObservable }) =>
+          expectObservable(fn(context, args)).toBe('(0|)', [
+            {
+              type: 'case',
+              matches: args.if,
+              result: context,
+            },
+          ])
+        );
       });
     });
   });
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.ts
index 7fba5b74e9b20..89329d6982716 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.ts
+++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.ts
@@ -5,15 +5,15 @@
  * 2.0.
  */
 
-import { Observable } from 'rxjs';
-import { take } from 'rxjs/operators';
+import { Observable, defer, isObservable, of } from 'rxjs';
+import { map, concatMap } from 'rxjs/operators';
 import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
 import { getFunctionHelp } from '../../../i18n';
 
 interface Arguments {
   when?(): Observable<any>;
   if?: boolean;
-  then?(): Observable<any>;
+  then(): Observable<any>;
 }
 
 interface Case {
@@ -22,7 +22,7 @@ interface Case {
   result: any;
 }
 
-export function caseFn(): ExpressionFunctionDefinition<'case', any, Arguments, Promise<Case>> {
+export function caseFn(): ExpressionFunctionDefinition<'case', any, Arguments, Observable<Case>> {
   const { help, args: argHelp } = getFunctionHelp().case;
 
   return {
@@ -45,24 +45,24 @@ export function caseFn(): ExpressionFunctionDefinition<'case', any, Arguments, P
         help: argHelp.then!,
       },
     },
-    fn: async (input, args) => {
-      const matches = await doesMatch(input, args);
-      const result = matches ? await getResult(input, args) : null;
-      return { type: 'case', matches, result };
+    fn(input, { if: condition, then, when }) {
+      return defer(() => {
+        const matches = condition ?? when?.().pipe(map((value) => value === input)) ?? true;
+
+        return isObservable(matches) ? matches : of(matches);
+      }).pipe(
+        concatMap((matches) =>
+          (matches ? then() : of(null)).pipe(
+            map(
+              (result): Case => ({
+                matches,
+                result,
+                type: 'case',
+              })
+            )
+          )
+        )
+      );
     },
   };
 }
-
-async function doesMatch(context: any, args: Arguments) {
-  if (typeof args.if !== 'undefined') {
-    return args.if;
-  }
-  if (typeof args.when !== 'undefined') {
-    return (await args.when().pipe(take(1)).toPromise()) === context;
-  }
-  return true;
-}
-
-async function getResult(context: any, args: Arguments) {
-  return args.then?.().pipe(take(1)).toPromise() ?? context;
-}
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js
index fdea4faa4ece2..8c328e3d8adf6 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js
+++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js
@@ -6,6 +6,7 @@
  */
 
 import { of } from 'rxjs';
+import { TestScheduler } from 'rxjs/testing';
 import { functionWrapper } from '../../../test_helpers/function_wrapper';
 import { testTable } from './__fixtures__/test_tables';
 import { filterrows } from './filterrows';
@@ -15,31 +16,46 @@ const returnFalse = () => of(false);
 
 describe('filterrows', () => {
   const fn = functionWrapper(filterrows);
+  let testScheduler;
+
+  beforeEach(() => {
+    testScheduler = new TestScheduler((actual, expected) => expect(actual).toStrictEqual(expected));
+  });
 
   it('returns a datable', () => {
-    expect(fn(testTable, { fn: inStock })).resolves.toHaveProperty('type', 'datatable');
+    testScheduler.run(({ expectObservable }) =>
+      expectObservable(fn(testTable, { fn: inStock })).toBe('(0|)', [
+        expect.objectContaining({ type: 'datatable' }),
+      ])
+    );
   });
 
   it('keeps rows that evaluate to true and removes rows that evaluate to false', () => {
     const inStockRows = testTable.rows.filter((row) => row.in_stock);
 
-    expect(fn(testTable, { fn: inStock })).resolves.toEqual(
-      expect.objectContaining({
-        columns: testTable.columns,
-        rows: inStockRows,
-      })
+    testScheduler.run(({ expectObservable }) =>
+      expectObservable(fn(testTable, { fn: inStock })).toBe('(0|)', [
+        expect.objectContaining({
+          columns: testTable.columns,
+          rows: inStockRows,
+        }),
+      ])
     );
   });
 
   it('returns datatable with no rows when no rows meet function condition', () => {
-    expect(fn(testTable, { fn: returnFalse })).resolves.toEqual(
-      expect.objectContaining({
-        rows: [],
-      })
+    testScheduler.run(({ expectObservable }) =>
+      expectObservable(fn(testTable, { fn: returnFalse })).toBe('(0|)', [
+        expect.objectContaining({
+          rows: [],
+        }),
+      ])
     );
   });
 
   it('throws when no function is provided', () => {
-    expect(() => fn(testTable)).toThrow('fn is not a function');
+    testScheduler.run(({ expectObservable }) =>
+      expectObservable(fn(testTable)).toBe('#', {}, new TypeError('fn is not a function'))
+    );
   });
 });
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.ts
index 082506f58e86f..4923b835d2871 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.ts
+++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.ts
@@ -5,8 +5,8 @@
  * 2.0.
  */
 
-import { Observable } from 'rxjs';
-import { take } from 'rxjs/operators';
+import { Observable, combineLatest, defer } from 'rxjs';
+import { map } from 'rxjs/operators';
 import { Datatable, ExpressionFunctionDefinition } from '../../../types';
 import { getFunctionHelp } from '../../../i18n';
 
@@ -18,7 +18,7 @@ export function filterrows(): ExpressionFunctionDefinition<
   'filterrows',
   Datatable,
   Arguments,
-  Promise<Datatable>
+  Observable<Datatable>
 > {
   const { help, args: argHelp } = getFunctionHelp().filterrows;
 
@@ -38,24 +38,12 @@ export function filterrows(): ExpressionFunctionDefinition<
       },
     },
     fn(input, { fn }) {
-      const checks = input.rows.map((row) =>
-        fn({
-          ...input,
-          rows: [row],
-        })
-          .pipe(take(1))
-          .toPromise()
+      return defer(() =>
+        combineLatest(input.rows.map((row) => fn({ ...input, rows: [row] })))
+      ).pipe(
+        map((checks) => input.rows.filter((row, i) => checks[i])),
+        map((rows) => ({ ...input, rows }))
       );
-
-      return Promise.all(checks)
-        .then((results) => input.rows.filter((row, i) => results[i]))
-        .then(
-          (rows) =>
-            ({
-              ...input,
-              rows,
-            } as Datatable)
-        );
     },
   };
 }
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.test.js
index 8e1106644105e..cab331807e44c 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.test.js
+++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.test.js
@@ -6,11 +6,17 @@
  */
 
 import { of } from 'rxjs';
+import { TestScheduler } from 'rxjs/testing';
 import { functionWrapper } from '../../../test_helpers/function_wrapper';
 import { ifFn } from './if';
 
 describe('if', () => {
   const fn = functionWrapper(ifFn);
+  let testScheduler;
+
+  beforeEach(() => {
+    testScheduler = new TestScheduler((actual, expected) => expect(actual).toStrictEqual(expected));
+  });
 
   describe('spec', () => {
     it('is a function', () => {
@@ -21,66 +27,73 @@ describe('if', () => {
   describe('function', () => {
     describe('condition passed', () => {
       it('with then', () => {
-        expect(fn(null, { condition: true, then: () => of('foo') })).resolves.toBe('foo');
-        expect(
-          fn(null, { condition: true, then: () => of('foo'), else: () => of('bar') })
-        ).resolves.toBe('foo');
+        testScheduler.run(({ expectObservable }) => {
+          expectObservable(fn(null, { condition: true, then: () => of('foo') })).toBe('(0|)', [
+            'foo',
+          ]);
+
+          expectObservable(
+            fn(null, { condition: true, then: () => of('foo'), else: () => of('bar') })
+          ).toBe('(0|)', ['foo']);
+        });
       });
 
       it('without then', () => {
-        expect(fn(null, { condition: true })).resolves.toBe(null);
-        expect(fn('some context', { condition: true })).resolves.toBe('some context');
+        testScheduler.run(({ expectObservable }) => {
+          expectObservable(fn(null, { condition: true })).toBe('(0|)', [null]);
+          expectObservable(fn('some context', { condition: true })).toBe('(0|)', ['some context']);
+        });
       });
     });
 
     describe('condition failed', () => {
-      it('with else', () =>
-        expect(
-          fn('some context', {
-            condition: false,
-            then: () => of('foo'),
-            else: () => of('bar'),
-          })
-        ).resolves.toBe('bar'));
-
-      it('without else', () =>
-        expect(fn('some context', { condition: false, then: () => of('foo') })).resolves.toBe(
-          'some context'
-        ));
-    });
-
-    describe('falsy values', () => {
-      describe('for then', () => {
-        it('with null', () => {
-          expect(fn('some context', { condition: true, then: () => of(null) })).resolves.toBe(null);
-        });
-
-        it('with false', () => {
-          expect(fn('some context', { condition: true, then: () => of(false) })).resolves.toBe(
-            false
-          );
-        });
-
-        it('with 0', () => {
-          expect(fn('some context', { condition: true, then: () => of(0) })).resolves.toBe(0);
+      it('with else', () => {
+        testScheduler.run(({ expectObservable }) => {
+          expectObservable(
+            fn('some context', {
+              condition: false,
+              then: () => of('foo'),
+              else: () => of('bar'),
+            })
+          ).toBe('(0|)', ['bar']);
         });
       });
 
-      describe('for else', () => {
-        it('with null', () => {
-          expect(fn('some context', { condition: false, else: () => of(null) })).resolves.toBe(
-            null
-          );
+      it('without else', () => {
+        testScheduler.run(({ expectObservable }) => {
+          expectObservable(
+            fn('some context', { condition: false, then: () => of('foo') })
+          ).toBe('(0|)', ['some context']);
         });
+      });
+    });
 
-        it('with false', () => {
-          expect(fn('some context', { condition: false, else: () => of(false) })).resolves.toBe(
-            false
-          );
+    describe('falsy values', () => {
+      // eslint-disable-next-line no-unsanitized/method
+      it.each`
+        value
+        ${null}
+        ${false}
+        ${0}
+      `('for then with $value', ({ value }) => {
+        testScheduler.run(({ expectObservable }) => {
+          expectObservable(
+            fn('some context', { condition: true, then: () => of(value) })
+          ).toBe('(0|)', [value]);
         });
+      });
 
-        it('with 0', () => {
-          expect(fn('some context', { condition: false, else: () => of(0) })).resolves.toBe(0);
+      // eslint-disable-next-line no-unsanitized/method
+      it.each`
+        value
+        ${null}
+        ${false}
+        ${0}
+      `('for else with $value', ({ value }) => {
+        testScheduler.run(({ expectObservable }) => {
+          expectObservable(
+            fn('some context', { condition: false, else: () => of(value) })
+          ).toBe('(0|)', [value]);
         });
       });
     });
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.ts
index 6d7665db551e4..82bfb87c173b0 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.ts
+++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.ts
@@ -5,18 +5,22 @@
  * 2.0.
  */
 
-import { Observable } from 'rxjs';
-import { take } from 'rxjs/operators';
+import { Observable, defer, of } from 'rxjs';
 import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
 import { getFunctionHelp } from '../../../i18n';
 
 interface Arguments {
-  condition: boolean | null;
+  condition: boolean;
   then?(): Observable<any>;
   else?(): Observable<any>;
 }
 
-export function ifFn(): ExpressionFunctionDefinition<'if', unknown, Arguments, unknown> {
+export function ifFn(): ExpressionFunctionDefinition<
+  'if',
+  unknown,
+  Arguments,
+  Observable<unknown>
+> {
   const { help, args: argHelp } = getFunctionHelp().if;
 
   return {
@@ -38,12 +42,8 @@ export function ifFn(): ExpressionFunctionDefinition<'if', unknown, Arguments, u
         help: argHelp.else!,
       },
     },
-    fn: async (input, args) => {
-      if (args.condition) {
-        return args.then?.().pipe(take(1)).toPromise() ?? input;
-      } else {
-        return args.else?.().pipe(take(1)).toPromise() ?? input;
-      }
+    fn(input, args) {
+      return defer(() => (args.condition ? args.then?.() : args.else?.()) ?? of(input));
     },
   };
 }
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js
index 74eca79395a10..5bf100eb90f4c 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js
+++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js
@@ -6,6 +6,7 @@
  */
 
 import { of } from 'rxjs';
+import { TestScheduler } from 'rxjs/testing';
 import { functionWrapper } from '../../../test_helpers/function_wrapper';
 import { getFunctionErrors } from '../../../i18n';
 import { testTable } from './__fixtures__/test_tables';
@@ -46,36 +47,56 @@ const rowCount = (datatable) =>
 
 describe('ply', () => {
   const fn = functionWrapper(ply);
+  let testScheduler;
 
-  it('maps a function over sub datatables grouped by specified columns and merges results into one datatable', async () => {
-    const arbitaryRowIndex = 0;
-    const result = await fn(testTable, {
-      by: ['name', 'in_stock'],
-      expression: [averagePrice, rowCount],
-    });
+  beforeEach(() => {
+    testScheduler = new TestScheduler((actual, expected) => expect(actual).toStrictEqual(expected));
+  });
 
-    expect(result.type).toBe('datatable');
-    expect(result.columns).toEqual([
-      { id: 'name', name: 'name', meta: { type: 'string' } },
-      { id: 'in_stock', name: 'in_stock', meta: { type: 'boolean' } },
-      { id: 'average_price', name: 'average_price', meta: { type: 'number' } },
-      { id: 'row_count', name: 'row_count', meta: { type: 'number' } },
-    ]);
-    expect(result.rows[arbitaryRowIndex]).toHaveProperty('average_price');
-    expect(result.rows[arbitaryRowIndex]).toHaveProperty('row_count');
+  it('maps a function over sub datatables grouped by specified columns and merges results into one datatable', () => {
+    testScheduler.run(({ expectObservable }) => {
+      expectObservable(
+        fn(testTable, {
+          by: ['name', 'in_stock'],
+          expression: [averagePrice, rowCount],
+        })
+      ).toBe('(0|)', [
+        expect.objectContaining({
+          type: 'datatable',
+          columns: [
+            { id: 'name', name: 'name', meta: { type: 'string' } },
+            { id: 'in_stock', name: 'in_stock', meta: { type: 'boolean' } },
+            { id: 'average_price', name: 'average_price', meta: { type: 'number' } },
+            { id: 'row_count', name: 'row_count', meta: { type: 'number' } },
+          ],
+          rows: expect.arrayContaining([
+            expect.objectContaining({
+              average_price: expect.anything(),
+              row_count: expect.anything(),
+            }),
+          ]),
+        }),
+      ]);
+    });
   });
 
   describe('missing args', () => {
     it('returns the original datatable if both args are missing', () => {
-      expect(fn(testTable)).resolves.toEqual(testTable);
+      testScheduler.run(({ expectObservable }) => {
+        expectObservable(fn(testTable)).toBe('(0|)', [testTable]);
+      });
     });
 
     describe('by', () => {
       it('passes the entire context into the expression when no columns are provided', () => {
-        expect(fn(testTable, { expression: [rowCount] })).resolves.toEqual({
-          type: 'datatable',
-          rows: [{ row_count: testTable.rows.length }],
-          columns: [{ id: 'row_count', name: 'row_count', meta: { type: 'number' } }],
+        testScheduler.run(({ expectObservable }) => {
+          expectObservable(fn(testTable, { expression: [rowCount] })).toBe('(0|)', [
+            {
+              type: 'datatable',
+              rows: [{ row_count: testTable.rows.length }],
+              columns: [{ id: 'row_count', name: 'row_count', meta: { type: 'number' } }],
+            },
+          ]);
         });
       });
 
@@ -91,24 +112,37 @@ describe('ply', () => {
     });
 
     describe('expression', () => {
-      it('returns the original datatable grouped by the specified columns', async () => {
-        const arbitaryRowIndex = 6;
-        const result = await fn(testTable, { by: ['price', 'quantity'] });
-
-        expect(result.columns[0]).toHaveProperty('name', 'price');
-        expect(result.columns[1]).toHaveProperty('name', 'quantity');
-        expect(result.rows[arbitaryRowIndex]).toHaveProperty('price');
-        expect(result.rows[arbitaryRowIndex]).toHaveProperty('quantity');
+      it('returns the original datatable grouped by the specified columns', () => {
+        testScheduler.run(({ expectObservable }) => {
+          expectObservable(fn(testTable, { by: ['price', 'quantity'] })).toBe('(0|)', [
+            expect.objectContaining({
+              columns: expect.arrayContaining([
+                expect.objectContaining({ name: 'price' }),
+                expect.objectContaining({ name: 'quantity' }),
+              ]),
+              rows: expect.arrayContaining([
+                expect.objectContaining({
+                  price: expect.anything(),
+                  quantity: expect.anything(),
+                }),
+              ]),
+            }),
+          ]);
+        });
       });
 
       it('throws when row counts do not match across resulting datatables', () => {
-        expect(
-          fn(testTable, { by: ['name'], expression: [doublePrice, rowCount] })
-        ).rejects.toEqual(
-          expect.objectContaining({
-            message: errors.rowCountMismatch().message,
-          })
-        );
+        testScheduler.run(({ expectObservable }) => {
+          expectObservable(
+            fn(testTable, { by: ['name'], expression: [doublePrice, rowCount] })
+          ).toBe(
+            '#',
+            [],
+            expect.objectContaining({
+              message: errors.rowCountMismatch().message,
+            })
+          );
+        });
       });
     });
   });
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.ts
index 514d7f73d48e4..322bf7fee980c 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.ts
+++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.ts
@@ -5,18 +5,18 @@
  * 2.0.
  */
 
-import { Observable } from 'rxjs';
-import { take } from 'rxjs/operators';
-import { groupBy, flatten, pick, map } from 'lodash';
+import { combineLatest, defer, of, Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
+import { groupBy, flatten, pick, map as _map, uniqWith } from 'lodash';
 import { Datatable, DatatableColumn, ExpressionFunctionDefinition } from '../../../types';
 import { getFunctionHelp, getFunctionErrors } from '../../../i18n';
 
 interface Arguments {
-  by: string[];
+  by?: string[];
   expression: Array<(datatable: Datatable) => Observable<Datatable>>;
 }
 
-type Output = Datatable | Promise<Datatable>;
+type Output = Datatable | Observable<Datatable>;
 
 export function ply(): ExpressionFunctionDefinition<'ply', Datatable, Arguments, Output> {
   const { help, args: argHelp } = getFunctionHelp().ply;
@@ -30,7 +30,7 @@ export function ply(): ExpressionFunctionDefinition<'ply', Datatable, Arguments,
     args: {
       by: {
         types: ['string'],
-        help: argHelp.by,
+        help: argHelp.by!,
         multi: true,
       },
       expression: {
@@ -41,86 +41,62 @@ export function ply(): ExpressionFunctionDefinition<'ply', Datatable, Arguments,
         help: argHelp.expression,
       },
     },
-    fn: (input, args) => {
+    fn(input, args) {
       if (!args) {
         return input;
       }
 
-      let byColumns: DatatableColumn[];
-      let originalDatatables: Datatable[];
-
-      if (args.by) {
-        byColumns = args.by.map((by) => {
-          const column = input.columns.find((col) => col.name === by);
+      const byColumns =
+        args.by?.map((by) => {
+          const column = input.columns.find(({ name }) => name === by);
 
           if (!column) {
             throw errors.columnNotFound(by);
           }
 
           return column;
-        });
-
-        const keyedDatatables = groupBy(input.rows, (row) => JSON.stringify(pick(row, args.by)));
-
-        originalDatatables = Object.values(keyedDatatables).map((rows) => ({
-          ...input,
-          rows,
-        }));
-      } else {
-        originalDatatables = [input];
-      }
-
-      const datatablePromises = originalDatatables.map((originalDatatable) => {
-        let expressionResultPromises = [];
-
-        if (args.expression) {
-          expressionResultPromises = args.expression.map((expression) =>
-            expression(originalDatatable).pipe(take(1)).toPromise()
+        }) ?? [];
+
+      const originalDatatables = args.by
+        ? Object.values(
+            groupBy(input.rows, (row) => JSON.stringify(pick(row, args.by!)))
+          ).map((rows) => ({ ...input, rows }))
+        : [input];
+
+      const datatables$ = originalDatatables.map((originalDatatable) =>
+        combineLatest(
+          args.expression?.map((expression) => defer(() => expression(originalDatatable))) ?? [
+            of(originalDatatable),
+          ]
+        ).pipe(map(combineAcross))
+      );
+
+      return (datatables$.length ? combineLatest(datatables$) : of([])).pipe(
+        map((newDatatables) => {
+          // Here we're just merging each for the by splits, so it doesn't actually matter if the rows are the same length
+          const columns = combineColumns([byColumns].concat(_map(newDatatables, 'columns')));
+          const rows = flatten(
+            newDatatables.map((datatable, index) =>
+              datatable.rows.map((row) => ({
+                ...pick(originalDatatables[index].rows[0], args.by!),
+                ...row,
+              }))
+            )
           );
-        } else {
-          expressionResultPromises.push(Promise.resolve(originalDatatable));
-        }
-
-        return Promise.all(expressionResultPromises).then(combineAcross);
-      });
-
-      return Promise.all(datatablePromises).then((newDatatables) => {
-        // Here we're just merging each for the by splits, so it doesn't actually matter if the rows are the same length
-        const columns = combineColumns([byColumns].concat(map(newDatatables, 'columns')));
-        const rows = flatten(
-          newDatatables.map((dt, i) => {
-            const byColumnValues = pick(originalDatatables[i].rows[0], args.by);
-            return dt.rows.map((row) => ({
-              ...byColumnValues,
-              ...row,
-            }));
-          })
-        );
-
-        return {
-          type: 'datatable',
-          rows,
-          columns,
-        } as Datatable;
-      });
+
+          return {
+            type: 'datatable',
+            rows,
+            columns,
+          } as Datatable;
+        })
+      );
     },
   };
 }
 
 function combineColumns(arrayOfColumnsArrays: DatatableColumn[][]) {
-  return arrayOfColumnsArrays.reduce((resultingColumns, columns) => {
-    if (columns) {
-      columns.forEach((column) => {
-        if (resultingColumns.find((resultingColumn) => resultingColumn.name === column.name)) {
-          return;
-        } else {
-          resultingColumns.push(column);
-        }
-      });
-    }
-
-    return resultingColumns;
-  }, []);
+  return uniqWith(arrayOfColumnsArrays.flat(), ({ name: a }, { name: b }) => a === b);
 }
 
 // This handles merging the tables produced by multiple expressions run on a single member of the `by` split.
@@ -138,17 +114,17 @@ function combineAcross(datatableArray: Datatable[]) {
   });
 
   // Merge columns and rows.
-  const arrayOfRowsArrays = map(datatableArray, 'rows');
+  const arrayOfRowsArrays = _map(datatableArray, 'rows');
   const rows = [];
   for (let i = 0; i < targetRowLength; i++) {
-    const rowsAcross = map(arrayOfRowsArrays, i);
+    const rowsAcross = _map(arrayOfRowsArrays, i);
 
     // The reason for the Object.assign is that rowsAcross is an array
     // and those rows need to be applied as arguments to Object.assign
     rows.push(Object.assign({}, ...rowsAcross));
   }
 
-  const columns = combineColumns(map(datatableArray, 'columns'));
+  const columns = combineColumns(_map(datatableArray, 'columns'));
 
   return {
     type: 'datatable',
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js
index 6d9a20dfeb487..7a6d483d6c72b 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js
+++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js
@@ -6,6 +6,7 @@
  */
 
 import { of } from 'rxjs';
+import { TestScheduler } from 'rxjs/testing';
 import { functionWrapper } from '../../../test_helpers/function_wrapper';
 import { switchFn } from './switch';
 
@@ -39,7 +40,13 @@ describe('switch', () => {
       result: 5,
     },
   ];
-  const nonMatchingCases = mockCases.filter((c) => !c.matches);
+  const nonMatchingCases = mockCases.filter(({ matches }) => !matches);
+
+  let testScheduler;
+
+  beforeEach(() => {
+    testScheduler = new TestScheduler((actual, expected) => expect(actual).toStrictEqual(expected));
+  });
 
   describe('spec', () => {
     it('is a function', () => {
@@ -51,13 +58,19 @@ describe('switch', () => {
     describe('with no cases', () => {
       it('should return the context if no default is provided', () => {
         const context = 'foo';
-        expect(fn(context, {})).resolves.toBe(context);
+
+        testScheduler.run(({ expectObservable }) =>
+          expectObservable(fn(context, {})).toBe('(0|)', [context])
+        );
       });
 
       it('should return the default if provided', () => {
         const context = 'foo';
         const args = { default: () => of('bar') };
-        expect(fn(context, args)).resolves.toBe('bar');
+
+        testScheduler.run(({ expectObservable }) =>
+          expectObservable(fn(context, args)).toBe('(0|)', ['bar'])
+        );
       });
     });
 
@@ -65,7 +78,10 @@ describe('switch', () => {
       it('should return the context if no default is provided', () => {
         const context = 'foo';
         const args = { case: nonMatchingCases.map(getter) };
-        expect(fn(context, args)).resolves.toBe(context);
+
+        testScheduler.run(({ expectObservable }) =>
+          expectObservable(fn(context, args)).toBe('(0|)', [context])
+        );
       });
 
       it('should return the default if provided', () => {
@@ -74,16 +90,22 @@ describe('switch', () => {
           case: nonMatchingCases.map(getter),
           default: () => of('bar'),
         };
-        expect(fn(context, args)).resolves.toBe('bar');
+
+        testScheduler.run(({ expectObservable }) =>
+          expectObservable(fn(context, args)).toBe('(0|)', ['bar'])
+        );
       });
     });
 
     describe('with matching cases', () => {
-      it('should return the first match', async () => {
+      it('should return the first match', () => {
         const context = 'foo';
         const args = { case: mockCases.map(getter) };
-        const firstMatch = mockCases.find((c) => c.matches);
-        expect(fn(context, args)).resolves.toBe(firstMatch.result);
+        const { result } = mockCases.find(({ matches }) => matches);
+
+        testScheduler.run(({ expectObservable }) =>
+          expectObservable(fn(context, args)).toBe('(0|)', [result])
+        );
       });
     });
   });
diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.ts
index 4258f56ec4cf5..f4e6c92c91cb6 100644
--- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.ts
+++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.ts
@@ -5,18 +5,23 @@
  * 2.0.
  */
 
-import { Observable } from 'rxjs';
-import { take } from 'rxjs/operators';
+import { Observable, defer, from, of } from 'rxjs';
+import { concatMap, filter, merge, pluck, take } from 'rxjs/operators';
 import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
 import { Case } from '../../../types';
 import { getFunctionHelp } from '../../../i18n';
 
 interface Arguments {
-  case: Array<() => Observable<Case>>;
+  case?: Array<() => Observable<Case>>;
   default?(): Observable<any>;
 }
 
-export function switchFn(): ExpressionFunctionDefinition<'switch', unknown, Arguments, unknown> {
+export function switchFn(): ExpressionFunctionDefinition<
+  'switch',
+  unknown,
+  Arguments,
+  Observable<unknown>
+> {
   const { help, args: argHelp } = getFunctionHelp().switch;
 
   return {
@@ -29,7 +34,7 @@ export function switchFn(): ExpressionFunctionDefinition<'switch', unknown, Argu
         resolve: false,
         multi: true,
         required: true,
-        help: argHelp.case,
+        help: argHelp.case!,
       },
       default: {
         aliases: ['finally'],
@@ -37,18 +42,14 @@ export function switchFn(): ExpressionFunctionDefinition<'switch', unknown, Argu
         help: argHelp.default!,
       },
     },
-    fn: async (input, args) => {
-      const cases = args.case || [];
-
-      for (let i = 0; i < cases.length; i++) {
-        const { matches, result } = await cases[i]().pipe(take(1)).toPromise();
-
-        if (matches) {
-          return result;
-        }
-      }
-
-      return args.default?.().pipe(take(1)).toPromise() ?? input;
+    fn(input, args) {
+      return from(args.case ?? []).pipe(
+        concatMap((item) => item()),
+        filter(({ matches }) => matches),
+        pluck('result'),
+        merge(defer(() => args.default?.() ?? of(input))),
+        take(1)
+      );
     },
   };
 }
diff --git a/x-pack/plugins/canvas/shareable_runtime/webpack.config.js b/x-pack/plugins/canvas/shareable_runtime/webpack.config.js
index e85840e873430..d0bdc292619d8 100644
--- a/x-pack/plugins/canvas/shareable_runtime/webpack.config.js
+++ b/x-pack/plugins/canvas/shareable_runtime/webpack.config.js
@@ -38,7 +38,7 @@ module.exports = {
         'src/plugins/data/public/expressions/interpreter'
       ),
       'kbn/interpreter': path.resolve(KIBANA_ROOT, 'packages/kbn-interpreter/target/common'),
-      tinymath: path.resolve(KIBANA_ROOT, 'node_modules/tinymath/lib/tinymath.es5.js'),
+      tinymath: path.resolve(KIBANA_ROOT, 'node_modules/tinymath/lib/tinymath.min.js'),
       core_app_image_assets: path.resolve(KIBANA_ROOT, 'src/core/public/core_app/images'),
     },
     extensions: ['.js', '.json', '.ts', '.tsx', '.scss'],
diff --git a/x-pack/plugins/cases/kibana.json b/x-pack/plugins/cases/kibana.json
index c59800aaf9bcb..4a85a64c7e03a 100644
--- a/x-pack/plugins/cases/kibana.json
+++ b/x-pack/plugins/cases/kibana.json
@@ -3,11 +3,15 @@
   "id": "cases",
   "kibanaVersion": "kibana",
   "extraPublicDirs": ["common"],
-  "requiredPlugins": ["actions", "esUiShared", "features", "kibanaReact", "kibanaUtils", "triggersActionsUi"],
-  "optionalPlugins": [
-    "spaces",
-    "security"
+  "requiredPlugins": [
+    "actions",
+    "esUiShared",
+    "features",
+    "kibanaReact",
+    "kibanaUtils",
+    "triggersActionsUi"
   ],
+  "optionalPlugins": ["spaces", "security"],
   "server": true,
   "ui": true,
   "version": "8.0.0"
diff --git a/x-pack/plugins/cases/public/components/all_cases/all_cases_generic.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_generic.tsx
index 41509d9c0d135..a364f8bf2b068 100644
--- a/x-pack/plugins/cases/public/components/all_cases/all_cases_generic.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_generic.tsx
@@ -62,9 +62,11 @@ interface AllCasesGenericProps {
   caseDetailsNavigation?: CasesNavigation<CaseDetailsHrefSchema, 'configurable'>; // if not passed, case name is not displayed as a link (Formerly dependant on isSelectorView)
   configureCasesNavigation?: CasesNavigation; // if not passed, header with nav is not displayed (Formerly dependant on isSelectorView)
   createCaseNavigation: CasesNavigation;
+  disableAlerts?: boolean;
   hiddenStatuses?: CaseStatusWithAllStatus[];
   isSelectorView?: boolean;
   onRowClick?: (theCase?: Case | SubCase) => void;
+  showTitle?: boolean;
   updateCase?: (newCase: Case) => void;
   userCanCrud: boolean;
 }
@@ -75,9 +77,11 @@ export const AllCasesGeneric = React.memo<AllCasesGenericProps>(
     caseDetailsNavigation,
     configureCasesNavigation,
     createCaseNavigation,
+    disableAlerts,
     hiddenStatuses = [],
     isSelectorView,
     onRowClick,
+    showTitle,
     updateCase,
     userCanCrud,
   }) => {
@@ -190,6 +194,7 @@ export const AllCasesGeneric = React.memo<AllCasesGenericProps>(
 
     const columns = useCasesColumns({
       caseDetailsNavigation,
+      disableAlerts,
       dispatchUpdateCaseProperty,
       filterStatus: filterOptions.status,
       handleIsLoading,
@@ -271,6 +276,7 @@ export const AllCasesGeneric = React.memo<AllCasesGenericProps>(
             createCaseNavigation={createCaseNavigation}
             configureCasesNavigation={configureCasesNavigation}
             refresh={refresh}
+            showTitle={showTitle}
             userCanCrud={userCanCrud}
           />
         )}
diff --git a/x-pack/plugins/cases/public/components/all_cases/columns.tsx b/x-pack/plugins/cases/public/components/all_cases/columns.tsx
index cf5da3928446e..947d405d188cf 100644
--- a/x-pack/plugins/cases/public/components/all_cases/columns.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/columns.tsx
@@ -55,6 +55,7 @@ const renderStringField = (field: string, dataTestSubj: string) =>
 
 export interface GetCasesColumn {
   caseDetailsNavigation?: CasesNavigation<CaseDetailsHrefSchema, 'configurable'>;
+  disableAlerts?: boolean;
   dispatchUpdateCaseProperty: (u: UpdateCase) => void;
   filterStatus: string;
   handleIsLoading: (a: boolean) => void;
@@ -64,6 +65,7 @@ export interface GetCasesColumn {
 }
 export const useCasesColumns = ({
   caseDetailsNavigation,
+  disableAlerts = false,
   dispatchUpdateCaseProperty,
   filterStatus,
   handleIsLoading,
@@ -203,15 +205,19 @@ export const useCasesColumns = ({
       },
       truncateText: true,
     },
-    {
-      align: RIGHT_ALIGNMENT,
-      field: 'totalAlerts',
-      name: ALERTS,
-      render: (totalAlerts: Case['totalAlerts']) =>
-        totalAlerts != null
-          ? renderStringField(`${totalAlerts}`, `case-table-column-alertsCount`)
-          : getEmptyTagValue(),
-    },
+    ...(!disableAlerts
+      ? [
+          {
+            align: RIGHT_ALIGNMENT,
+            field: 'totalAlerts',
+            name: ALERTS,
+            render: (totalAlerts: Case['totalAlerts']) =>
+              totalAlerts != null
+                ? renderStringField(`${totalAlerts}`, `case-table-column-alertsCount`)
+                : getEmptyTagValue(),
+          },
+        ]
+      : []),
     {
       align: RIGHT_ALIGNMENT,
       field: 'totalComment',
diff --git a/x-pack/plugins/cases/public/components/all_cases/header.tsx b/x-pack/plugins/cases/public/components/all_cases/header.tsx
index a6737b987e2c4..7452fe7e44b3c 100644
--- a/x-pack/plugins/cases/public/components/all_cases/header.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/header.tsx
@@ -20,6 +20,7 @@ interface OwnProps {
   configureCasesNavigation: CasesNavigation;
   createCaseNavigation: CasesNavigation;
   refresh: number;
+  showTitle?: boolean;
   userCanCrud: boolean;
 }
 
@@ -40,9 +41,10 @@ export const CasesTableHeader: FunctionComponent<Props> = ({
   configureCasesNavigation,
   createCaseNavigation,
   refresh,
+  showTitle = true,
   userCanCrud,
 }) => (
-  <CaseHeaderPage title={i18n.PAGE_TITLE}>
+  <CaseHeaderPage title={showTitle ? i18n.PAGE_TITLE : ''}>
     <EuiFlexGroup
       alignItems="center"
       gutterSize="m"
diff --git a/x-pack/plugins/cases/public/components/all_cases/index.tsx b/x-pack/plugins/cases/public/components/all_cases/index.tsx
index 3d6c039aa001c..1f836b318dbad 100644
--- a/x-pack/plugins/cases/public/components/all_cases/index.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/index.tsx
@@ -14,6 +14,8 @@ export interface AllCasesProps extends Owner {
   caseDetailsNavigation: CasesNavigation<CaseDetailsHrefSchema, 'configurable'>; // if not passed, case name is not displayed as a link (Formerly dependant on isSelector)
   configureCasesNavigation: CasesNavigation; // if not passed, header with nav is not displayed (Formerly dependant on isSelector)
   createCaseNavigation: CasesNavigation;
+  disableAlerts?: boolean;
+  showTitle?: boolean;
   userCanCrud: boolean;
 }
 
diff --git a/x-pack/plugins/cases/public/components/callout/callout.test.tsx b/x-pack/plugins/cases/public/components/callout/callout.test.tsx
index 926fe7b63fb5a..0a0caa40a8783 100644
--- a/x-pack/plugins/cases/public/components/callout/callout.test.tsx
+++ b/x-pack/plugins/cases/public/components/callout/callout.test.tsx
@@ -80,7 +80,7 @@ describe('Callout', () => {
   });
 
   it('dismiss the callout correctly', () => {
-    const wrapper = mount(<CallOut {...defaultProps} messages={[]} />);
+    const wrapper = mount(<CallOut {...defaultProps} />);
     expect(wrapper.find(`[data-test-subj="callout-dismiss-md5-hex"]`).exists()).toBeTruthy();
     wrapper.find(`button[data-test-subj="callout-dismiss-md5-hex"]`).simulate('click');
     wrapper.update();
diff --git a/x-pack/plugins/cases/public/components/callout/callout.tsx b/x-pack/plugins/cases/public/components/callout/callout.tsx
index 8e2f439f02c4b..4cd7fad10fe70 100644
--- a/x-pack/plugins/cases/public/components/callout/callout.tsx
+++ b/x-pack/plugins/cases/public/components/callout/callout.tsx
@@ -35,11 +35,9 @@ const CallOutComponent = ({
     type,
   ]);
 
-  return showCallOut ? (
+  return showCallOut && !isEmpty(messages) ? (
     <EuiCallOut title={title} color={type} iconType="gear" data-test-subj={`case-callout-${id}`}>
-      {!isEmpty(messages) && (
-        <EuiDescriptionList data-test-subj={`callout-messages-${id}`} listItems={messages} />
-      )}
+      <EuiDescriptionList data-test-subj={`callout-messages-${id}`} listItems={messages} />
       <EuiButton
         data-test-subj={`callout-dismiss-${id}`}
         color={type === 'success' ? 'secondary' : type}
diff --git a/x-pack/plugins/cases/public/components/callout/helpers.tsx b/x-pack/plugins/cases/public/components/callout/helpers.tsx
index 3409c5eb94245..29b17cd426c58 100644
--- a/x-pack/plugins/cases/public/components/callout/helpers.tsx
+++ b/x-pack/plugins/cases/public/components/callout/helpers.tsx
@@ -11,7 +11,7 @@ import md5 from 'md5';
 import * as i18n from './translations';
 import { ErrorMessage } from './types';
 
-export const savedObjectReadOnlyErrorMessage: ErrorMessage = {
+export const permissionsReadOnlyErrorMessage: ErrorMessage = {
   id: 'read-only-privileges-error',
   title: i18n.READ_ONLY_FEATURE_TITLE,
   description: <>{i18n.READ_ONLY_FEATURE_MSG}</>,
diff --git a/x-pack/plugins/cases/public/components/case_action_bar/actions.test.tsx b/x-pack/plugins/cases/public/components/case_action_bar/actions.test.tsx
index 886e740d56447..ed8e238db75e7 100644
--- a/x-pack/plugins/cases/public/components/case_action_bar/actions.test.tsx
+++ b/x-pack/plugins/cases/public/components/case_action_bar/actions.test.tsx
@@ -26,7 +26,14 @@ jest.mock('react-router-dom', () => {
     }),
   };
 });
-
+const defaultProps = {
+  allCasesNavigation: {
+    href: 'all-cases-href',
+    onClick: () => {},
+  },
+  caseData: basicCase,
+  currentExternalIncident: null,
+};
 describe('CaseView actions', () => {
   const handleOnDeleteConfirm = jest.fn();
   const handleToggleModal = jest.fn();
@@ -49,7 +56,7 @@ describe('CaseView actions', () => {
   it('clicking trash toggles modal', () => {
     const wrapper = mount(
       <TestProviders>
-        <Actions caseData={basicCase} currentExternalIncident={null} />
+        <Actions {...defaultProps} />
       </TestProviders>
     );
 
@@ -67,7 +74,7 @@ describe('CaseView actions', () => {
     }));
     const wrapper = mount(
       <TestProviders>
-        <Actions caseData={basicCase} currentExternalIncident={null} />
+        <Actions {...defaultProps} />
       </TestProviders>
     );
 
@@ -82,7 +89,7 @@ describe('CaseView actions', () => {
     const wrapper = mount(
       <TestProviders>
         <Actions
-          caseData={basicCase}
+          {...defaultProps}
           currentExternalIncident={{
             ...basicPush,
             firstPushIndex: 5,
diff --git a/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx b/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx
index b8d9d7f85a9ef..922ffd09aaac9 100644
--- a/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx
+++ b/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx
@@ -7,26 +7,27 @@
 
 import { isEmpty } from 'lodash/fp';
 import React, { useMemo } from 'react';
-import { useHistory } from 'react-router-dom';
 import * as i18n from '../case_view/translations';
 import { useDeleteCases } from '../../containers/use_delete_cases';
 import { ConfirmDeleteCaseModal } from '../confirm_delete_case';
 import { PropertyActions } from '../property_actions';
-import { Case } from '../../containers/types';
+import { Case } from '../../../common';
 import { CaseService } from '../../containers/use_get_case_user_actions';
+import { CasesNavigation } from '../links';
 
 interface CaseViewActions {
+  allCasesNavigation: CasesNavigation;
   caseData: Case;
   currentExternalIncident: CaseService | null;
   disabled?: boolean;
 }
 
 const ActionsComponent: React.FC<CaseViewActions> = ({
+  allCasesNavigation,
   caseData,
   currentExternalIncident,
   disabled = false,
 }) => {
-  const history = useHistory();
   // Delete case
   const {
     handleToggleModal,
@@ -57,7 +58,7 @@ const ActionsComponent: React.FC<CaseViewActions> = ({
   );
 
   if (isDeleted) {
-    history.push('/');
+    allCasesNavigation.onClick(null);
     return null;
   }
   return (
diff --git a/x-pack/plugins/cases/public/components/case_action_bar/index.test.tsx b/x-pack/plugins/cases/public/components/case_action_bar/index.test.tsx
index 0d29335ea730e..724d35b20df53 100644
--- a/x-pack/plugins/cases/public/components/case_action_bar/index.test.tsx
+++ b/x-pack/plugins/cases/public/components/case_action_bar/index.test.tsx
@@ -16,7 +16,12 @@ describe('CaseActionBar', () => {
   const onRefresh = jest.fn();
   const onUpdateField = jest.fn();
   const defaultProps = {
+    allCasesNavigation: {
+      href: 'all-cases-href',
+      onClick: () => {},
+    },
     caseData: basicCase,
+    disableAlerting: false,
     isLoading: false,
     onRefresh,
     onUpdateField,
diff --git a/x-pack/plugins/cases/public/components/case_action_bar/index.tsx b/x-pack/plugins/cases/public/components/case_action_bar/index.tsx
index a68ae4b3ca6a7..d8e012b072106 100644
--- a/x-pack/plugins/cases/public/components/case_action_bar/index.tsx
+++ b/x-pack/plugins/cases/public/components/case_action_bar/index.tsx
@@ -16,16 +16,16 @@ import {
   EuiFlexItem,
   EuiIconTip,
 } from '@elastic/eui';
-import { CaseStatuses, CaseType } from '../../../common';
+import { Case, CaseStatuses, CaseType } from '../../../common';
 import * as i18n from '../case_view/translations';
 import { FormattedRelativePreferenceDate } from '../formatted_date';
 import { Actions } from './actions';
-import { Case } from '../../containers/types';
 import { CaseService } from '../../containers/use_get_case_user_actions';
 import { StatusContextMenu } from './status_context_menu';
 import { getStatusDate, getStatusTitle } from './helpers';
 import { SyncAlertsSwitch } from '../case_settings/sync_alerts_switch';
 import { OnUpdateFields } from '../case_view';
+import { CasesNavigation } from '../links';
 
 const MyDescriptionList = styled(EuiDescriptionList)`
   ${({ theme }) => css`
@@ -37,17 +37,21 @@ const MyDescriptionList = styled(EuiDescriptionList)`
 `;
 
 interface CaseActionBarProps {
+  allCasesNavigation: CasesNavigation;
   caseData: Case;
   currentExternalIncident: CaseService | null;
   disabled?: boolean;
+  disableAlerting: boolean;
   isLoading: boolean;
   onRefresh: () => void;
   onUpdateField: (args: OnUpdateFields) => void;
 }
 const CaseActionBarComponent: React.FC<CaseActionBarProps> = ({
+  allCasesNavigation,
   caseData,
   currentExternalIncident,
   disabled = false,
+  disableAlerting,
   isLoading,
   onRefresh,
   onUpdateField,
@@ -104,25 +108,27 @@ const CaseActionBarComponent: React.FC<CaseActionBarProps> = ({
       <EuiFlexItem grow={false}>
         <EuiDescriptionList compressed>
           <EuiFlexGroup gutterSize="l" alignItems="center">
-            <EuiFlexItem>
-              <EuiDescriptionListTitle>
-                <EuiFlexGroup component="span" alignItems="center" gutterSize="xs">
-                  <EuiFlexItem grow={false}>
-                    <span>{i18n.SYNC_ALERTS}</span>
-                  </EuiFlexItem>
-                  <EuiFlexItem grow={false}>
-                    <EuiIconTip content={i18n.SYNC_ALERTS_HELP} />
-                  </EuiFlexItem>
-                </EuiFlexGroup>
-              </EuiDescriptionListTitle>
-              <EuiDescriptionListDescription>
-                <SyncAlertsSwitch
-                  disabled={disabled || isLoading}
-                  isSynced={caseData.settings.syncAlerts}
-                  onSwitchChange={onSyncAlertsChanged}
-                />
-              </EuiDescriptionListDescription>
-            </EuiFlexItem>
+            {!disableAlerting && (
+              <EuiFlexItem>
+                <EuiDescriptionListTitle>
+                  <EuiFlexGroup component="span" alignItems="center" gutterSize="xs">
+                    <EuiFlexItem grow={false}>
+                      <span>{i18n.SYNC_ALERTS}</span>
+                    </EuiFlexItem>
+                    <EuiFlexItem grow={false}>
+                      <EuiIconTip content={i18n.SYNC_ALERTS_HELP} />
+                    </EuiFlexItem>
+                  </EuiFlexGroup>
+                </EuiDescriptionListTitle>
+                <EuiDescriptionListDescription>
+                  <SyncAlertsSwitch
+                    disabled={disabled || isLoading}
+                    isSynced={caseData.settings.syncAlerts}
+                    onSwitchChange={onSyncAlertsChanged}
+                  />
+                </EuiDescriptionListDescription>
+              </EuiFlexItem>
+            )}
             <EuiFlexItem>
               <EuiButtonEmpty data-test-subj="case-refresh" iconType="refresh" onClick={onRefresh}>
                 {i18n.CASE_REFRESH}
@@ -130,6 +136,7 @@ const CaseActionBarComponent: React.FC<CaseActionBarProps> = ({
             </EuiFlexItem>
             <EuiFlexItem grow={false} data-test-subj="case-view-actions">
               <Actions
+                allCasesNavigation={allCasesNavigation}
                 caseData={caseData}
                 currentExternalIncident={currentExternalIncident}
                 disabled={disabled}
diff --git a/x-pack/plugins/cases/public/components/case_view/does_not_exist.tsx b/x-pack/plugins/cases/public/components/case_view/does_not_exist.tsx
new file mode 100644
index 0000000000000..627c90a45aa66
--- /dev/null
+++ b/x-pack/plugins/cases/public/components/case_view/does_not_exist.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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';
+import * as i18n from './translations';
+import { CasesNavigation } from '../links';
+
+interface Props {
+  allCasesNavigation: CasesNavigation;
+  caseId: string;
+}
+
+export const DoesNotExist = ({ allCasesNavigation, caseId }: Props) => (
+  <EuiEmptyPrompt
+    iconColor="default"
+    iconType="addDataApp"
+    title={<h2>{i18n.DOES_NOT_EXIST_TITLE}</h2>}
+    titleSize="xs"
+    body={<p>{i18n.DOES_NOT_EXIST_DESCRIPTION(caseId)}</p>}
+    actions={
+      <EuiButton onClick={allCasesNavigation.onClick} size="s" color="primary" fill>
+        {i18n.DOES_NOT_EXIST_BUTTON}
+      </EuiButton>
+    }
+  />
+);
diff --git a/x-pack/plugins/cases/public/components/case_view/index.tsx b/x-pack/plugins/cases/public/components/case_view/index.tsx
index 86b13ae5a863c..df57e49073a60 100644
--- a/x-pack/plugins/cases/public/components/case_view/index.tsx
+++ b/x-pack/plugins/cases/public/components/case_view/index.tsx
@@ -6,7 +6,6 @@
  */
 
 import React, { useCallback, useEffect, useMemo, useState, useRef } from 'react';
-// import { useDispatch } from 'react-redux';
 import styled from 'styled-components';
 import { isEmpty } from 'lodash/fp';
 import {
@@ -17,7 +16,7 @@ import {
   EuiHorizontalRule,
 } from '@elastic/eui';
 
-import { CaseStatuses, CaseAttributes, CaseType, Case, CaseConnector } from '../../../common';
+import { CaseStatuses, CaseAttributes, CaseType, Case, CaseConnector, Ecs } from '../../../common';
 import { HeaderPage } from '../header_page';
 import { EditableTitle } from '../header_page/editable_title';
 import { TagList } from '../tag_list';
@@ -39,11 +38,11 @@ import {
 } from '../configure_cases/utils';
 import { StatusActionButton } from '../status/button';
 import * as i18n from './translations';
-import { Ecs } from '../../../common';
 import { CasesTimelineIntegration, CasesTimelineIntegrationProvider } from '../timeline_context';
 import { useTimelineContext } from '../timeline_context/use_timeline_context';
 import { CasesNavigation } from '../links';
 import { OwnerProvider } from '../owner_context';
+import { DoesNotExist } from './does_not_exist';
 
 const gutterTimeline = '70px'; // seems to be a timeline reference from the original file
 export interface CaseViewComponentProps {
@@ -53,8 +52,8 @@ export interface CaseViewComponentProps {
   configureCasesNavigation: CasesNavigation;
   getCaseDetailHrefWithCommentId: (commentId: string) => string;
   onComponentInitialized?: () => void;
-  ruleDetailsNavigation: CasesNavigation<string | null | undefined, 'configurable'>;
-  showAlertDetails: (alertId: string, index: string) => void;
+  ruleDetailsNavigation?: CasesNavigation<string | null | undefined, 'configurable'>;
+  showAlertDetails?: (alertId: string, index: string) => void;
   subCaseId?: string;
   useFetchAlertData: (alertIds: string[]) => [boolean, Record<string, Ecs>];
   userCanCrud: boolean;
@@ -327,7 +326,9 @@ export const CaseComponent = React.memo<CaseComponentProps>(
 
     const onShowAlertDetails = useCallback(
       (alertId: string, index: string) => {
-        showAlertDetails(alertId, index);
+        if (showAlertDetails) {
+          showAlertDetails(alertId, index);
+        }
       },
       [showAlertDetails]
     );
@@ -359,9 +360,11 @@ export const CaseComponent = React.memo<CaseComponentProps>(
             title={caseData.title}
           >
             <CaseActionBar
-              currentExternalIncident={currentExternalIncident}
+              allCasesNavigation={allCasesNavigation}
               caseData={caseData}
+              currentExternalIncident={currentExternalIncident}
               disabled={!userCanCrud}
+              disableAlerting={ruleDetailsNavigation == null}
               isLoading={isLoading && (updateKey === 'status' || updateKey === 'settings')}
               onRefresh={handleRefresh}
               onUpdateField={onUpdateField}
@@ -380,8 +383,8 @@ export const CaseComponent = React.memo<CaseComponentProps>(
                   <>
                     <UserActionTree
                       getCaseDetailHrefWithCommentId={getCaseDetailHrefWithCommentId}
-                      getRuleDetailsHref={ruleDetailsNavigation.href}
-                      onRuleDetailsClick={ruleDetailsNavigation.onClick}
+                      getRuleDetailsHref={ruleDetailsNavigation?.href}
+                      onRuleDetailsClick={ruleDetailsNavigation?.onClick}
                       caseServices={caseServices}
                       caseUserActions={caseUserActions}
                       connectors={connectors}
@@ -493,7 +496,7 @@ export const CaseView = React.memo(
   }: CaseViewProps) => {
     const { data, isLoading, isError, fetchCase, updateCase } = useGetCase(caseId, subCaseId);
     if (isError) {
-      return null;
+      return <DoesNotExist allCasesNavigation={allCasesNavigation} caseId={caseId} />;
     }
     if (isLoading) {
       return (
diff --git a/x-pack/plugins/cases/public/components/case_view/translations.ts b/x-pack/plugins/cases/public/components/case_view/translations.ts
index 41ffbbd9342da..3d4558ac3d4a0 100644
--- a/x-pack/plugins/cases/public/components/case_view/translations.ts
+++ b/x-pack/plugins/cases/public/components/case_view/translations.ts
@@ -128,3 +128,20 @@ export const CHANGED_CONNECTOR_FIELD = i18n.translate('xpack.cases.caseView.fiel
 export const SYNC_ALERTS = i18n.translate('xpack.cases.caseView.syncAlertsLabel', {
   defaultMessage: `Sync alerts`,
 });
+
+export const DOES_NOT_EXIST_TITLE = i18n.translate('xpack.cases.caseView.doesNotExist.title', {
+  defaultMessage: 'This case does not exist',
+});
+
+export const DOES_NOT_EXIST_DESCRIPTION = (caseId: string) =>
+  i18n.translate('xpack.cases.caseView.doesNotExist.description', {
+    values: {
+      caseId,
+    },
+    defaultMessage:
+      'A case with id {caseId} could not be found. This likely means the case has been deleted, or the id is incorrect.',
+  });
+
+export const DOES_NOT_EXIST_BUTTON = i18n.translate('xpack.cases.caseView.doesNotExist.button', {
+  defaultMessage: 'Back to Cases',
+});
diff --git a/x-pack/plugins/cases/public/components/create/form.tsx b/x-pack/plugins/cases/public/components/create/form.tsx
index 83f759947ba65..cbd4fd7654259 100644
--- a/x-pack/plugins/cases/public/components/create/form.tsx
+++ b/x-pack/plugins/cases/public/components/create/form.tsx
@@ -38,6 +38,7 @@ const MySpinner = styled(EuiLoadingSpinner)`
 
 interface Props {
   connectors?: ActionConnector[];
+  disableAlerts?: boolean;
   hideConnectorServiceNowSir?: boolean;
   isLoadingConnectors?: boolean;
   withSteps?: boolean;
@@ -46,6 +47,7 @@ const empty: ActionConnector[] = [];
 export const CreateCaseForm: React.FC<Props> = React.memo(
   ({
     connectors = empty,
+    disableAlerts = false,
     isLoadingConnectors = false,
     hideConnectorServiceNowSir = false,
     withSteps = true,
@@ -99,11 +101,10 @@ export const CreateCaseForm: React.FC<Props> = React.memo(
       [connectors, hideConnectorServiceNowSir, isLoadingConnectors, isSubmitting]
     );
 
-    const allSteps = useMemo(() => [firstStep, secondStep, thirdStep], [
-      firstStep,
-      secondStep,
-      thirdStep,
-    ]);
+    const allSteps = useMemo(
+      () => [firstStep, ...(!disableAlerts ? [secondStep] : []), thirdStep],
+      [disableAlerts, firstStep, secondStep, thirdStep]
+    );
 
     return (
       <>
@@ -117,7 +118,7 @@ export const CreateCaseForm: React.FC<Props> = React.memo(
         ) : (
           <>
             {firstStep.children}
-            {secondStep.children}
+            {!disableAlerts && secondStep.children}
             {thirdStep.children}
           </>
         )}
diff --git a/x-pack/plugins/cases/public/components/create/form_context.tsx b/x-pack/plugins/cases/public/components/create/form_context.tsx
index 8584892e1286c..30a60fb5c1e47 100644
--- a/x-pack/plugins/cases/public/components/create/form_context.tsx
+++ b/x-pack/plugins/cases/public/components/create/form_context.tsx
@@ -73,7 +73,7 @@ export const FormContext: React.FC<Props> = ({
 
   const submitCase = useCallback(
     async (
-      { connectorId: dataConnectorId, fields, syncAlerts, ...dataWithoutConnectorId },
+      { connectorId: dataConnectorId, fields, syncAlerts = true, ...dataWithoutConnectorId },
       isValid
     ) => {
       if (isValid) {
diff --git a/x-pack/plugins/cases/public/components/create/index.tsx b/x-pack/plugins/cases/public/components/create/index.tsx
index 3362aa6af2078..139a2103f6042 100644
--- a/x-pack/plugins/cases/public/components/create/index.tsx
+++ b/x-pack/plugins/cases/public/components/create/index.tsx
@@ -34,6 +34,7 @@ const Container = styled.div`
 export interface CreateCaseProps extends Owner {
   afterCaseCreated?: (theCase: Case, postComment: UsePostComment['postComment']) => Promise<void>;
   caseType?: CaseType;
+  disableAlerts?: boolean;
   hideConnectorServiceNowSir?: boolean;
   onCancel: () => void;
   onSuccess: (theCase: Case) => Promise<void>;
@@ -45,6 +46,7 @@ const CreateCaseComponent = ({
   afterCaseCreated,
   caseType,
   hideConnectorServiceNowSir,
+  disableAlerts,
   onCancel,
   onSuccess,
   timelineIntegration,
@@ -59,6 +61,7 @@ const CreateCaseComponent = ({
     >
       <CreateCaseForm
         hideConnectorServiceNowSir={hideConnectorServiceNowSir}
+        disableAlerts={disableAlerts}
         withSteps={withSteps}
       />
       <Container>
diff --git a/x-pack/plugins/cases/public/components/links/index.tsx b/x-pack/plugins/cases/public/components/links/index.tsx
index 310d700aa2a25..23eedc7c090bc 100644
--- a/x-pack/plugins/cases/public/components/links/index.tsx
+++ b/x-pack/plugins/cases/public/components/links/index.tsx
@@ -16,7 +16,7 @@ import {
 import React, { useCallback } from 'react';
 import * as i18n from './translations';
 
-export interface CasesNavigation<T = React.MouseEvent | MouseEvent, K = null> {
+export interface CasesNavigation<T = React.MouseEvent | MouseEvent | null, K = null> {
   href: K extends 'configurable' ? (arg: T) => string : string;
   onClick: (arg: T) => void;
 }
diff --git a/x-pack/plugins/cases/public/components/use_push_to_service/index.tsx b/x-pack/plugins/cases/public/components/use_push_to_service/index.tsx
index a4ce8e3d92522..1b8e01b15db8d 100644
--- a/x-pack/plugins/cases/public/components/use_push_to_service/index.tsx
+++ b/x-pack/plugins/cases/public/components/use_push_to_service/index.tsx
@@ -38,7 +38,7 @@ export interface ReturnUsePushToService {
 }
 
 export const usePushToService = ({
-  configureCasesNavigation: { onClick, href },
+  configureCasesNavigation: { href },
   connector,
   caseId,
   caseServices,
@@ -82,7 +82,7 @@ export const usePushToService = ({
               id="xpack.cases.caseView.pushToServiceDisableByNoConnectors"
               values={{
                 link: (
-                  <LinkAnchor onClick={onClick} href={href} target="_blank">
+                  <LinkAnchor href={href} target="_blank">
                     {i18n.LINK_CONNECTOR_CONFIGURE}
                   </LinkAnchor>
                 ),
diff --git a/x-pack/plugins/cases/public/components/user_action_tree/index.tsx b/x-pack/plugins/cases/public/components/user_action_tree/index.tsx
index 09b024fb2ca3d..156e011a18d8d 100644
--- a/x-pack/plugins/cases/public/components/user_action_tree/index.tsx
+++ b/x-pack/plugins/cases/public/components/user_action_tree/index.tsx
@@ -21,7 +21,7 @@ import { isRight } from 'fp-ts/Either';
 
 import * as i18n from './translations';
 
-import { Case, CaseUserActions } from '../../containers/types';
+import { Case, CaseUserActions } from '../../../common';
 import { useUpdateComment } from '../../containers/use_update_comment';
 import { useCurrentUser } from '../../common/lib/kibana';
 import { AddComment, AddCommentRefObject } from '../add_comment';
@@ -56,7 +56,7 @@ export interface UserActionTreeProps {
   caseUserActions: CaseUserActions[];
   connectors: ActionConnector[];
   data: Case;
-  getRuleDetailsHref: (ruleId: string | null | undefined) => string;
+  getRuleDetailsHref?: (ruleId: string | null | undefined) => string;
   fetchUserActions: () => void;
   isLoadingDescription: boolean;
   isLoadingUserActions: boolean;
@@ -397,18 +397,22 @@ export const UserActionTree = React.memo(
 
                 return [
                   ...comments,
-                  getAlertAttachment({
-                    action,
-                    alertId,
-                    getCaseDetailHrefWithCommentId,
-                    getRuleDetailsHref,
-                    index: alertIndex,
-                    loadingAlertData,
-                    onRuleDetailsClick,
-                    ruleId,
-                    ruleName,
-                    onShowAlertDetails,
-                  }),
+                  ...(getRuleDetailsHref != null
+                    ? [
+                        getAlertAttachment({
+                          action,
+                          alertId,
+                          getCaseDetailHrefWithCommentId,
+                          getRuleDetailsHref,
+                          index: alertIndex,
+                          loadingAlertData,
+                          onRuleDetailsClick,
+                          ruleId,
+                          ruleName,
+                          onShowAlertDetails,
+                        }),
+                      ]
+                    : []),
                 ];
               } else if (comment != null && comment.type === CommentType.generatedAlert) {
                 // TODO: clean this up
@@ -422,16 +426,20 @@ export const UserActionTree = React.memo(
 
                 return [
                   ...comments,
-                  getGeneratedAlertsAttachment({
-                    action,
-                    alertIds,
-                    getCaseDetailHrefWithCommentId,
-                    getRuleDetailsHref,
-                    onRuleDetailsClick,
-                    renderInvestigateInTimelineActionComponent,
-                    ruleId: comment.rule?.id ?? '',
-                    ruleName: comment.rule?.name ?? i18n.UNKNOWN_RULE,
-                  }),
+                  ...(getRuleDetailsHref != null
+                    ? [
+                        getGeneratedAlertsAttachment({
+                          action,
+                          alertIds,
+                          getCaseDetailHrefWithCommentId,
+                          getRuleDetailsHref,
+                          onRuleDetailsClick,
+                          renderInvestigateInTimelineActionComponent,
+                          ruleId: comment.rule?.id ?? '',
+                          ruleName: comment.rule?.name ?? i18n.UNKNOWN_RULE,
+                        }),
+                      ]
+                    : []),
                 ];
               }
             }
diff --git a/x-pack/plugins/cases/public/containers/api.test.tsx b/x-pack/plugins/cases/public/containers/api.test.tsx
index afd6b51b5f35d..f9e128e7f713d 100644
--- a/x-pack/plugins/cases/public/containers/api.test.tsx
+++ b/x-pack/plugins/cases/public/containers/api.test.tsx
@@ -161,7 +161,7 @@ describe('Case Configuration API', () => {
         query: {
           ...DEFAULT_QUERY_PARAMS,
           reporters,
-          tags: ['"coke"', '"pepsi"'],
+          tags: ['coke', 'pepsi'],
           search: 'hello',
           status: CaseStatuses.open,
           owner: [SECURITY_SOLUTION_OWNER],
@@ -190,7 +190,7 @@ describe('Case Configuration API', () => {
         query: {
           ...DEFAULT_QUERY_PARAMS,
           reporters,
-          tags: ['"("', '"\\"double\\""'],
+          tags: ['(', '"double"'],
           search: 'hello',
           status: CaseStatuses.open,
           owner: [SECURITY_SOLUTION_OWNER],
diff --git a/x-pack/plugins/cases/public/containers/api.ts b/x-pack/plugins/cases/public/containers/api.ts
index 66a4d174b0ffb..fc1dc34b4e1ac 100644
--- a/x-pack/plugins/cases/public/containers/api.ts
+++ b/x-pack/plugins/cases/public/containers/api.ts
@@ -189,7 +189,7 @@ export const getCases = async ({
 }: FetchCasesProps): Promise<AllCases> => {
   const query = {
     reporters: filterOptions.reporters.map((r) => r.username ?? '').filter((r) => r !== ''),
-    tags: filterOptions.tags.map((t) => `"${t.replace(/"/g, '\\"')}"`),
+    tags: filterOptions.tags,
     status: filterOptions.status,
     ...(filterOptions.search.length > 0 ? { search: filterOptions.search } : {}),
     ...(filterOptions.onlyCollectionType ? { type: CaseType.collection } : {}),
diff --git a/x-pack/plugins/cases/public/index.tsx b/x-pack/plugins/cases/public/index.tsx
index e8589152b7ca8..a33bb14cd78c1 100644
--- a/x-pack/plugins/cases/public/index.tsx
+++ b/x-pack/plugins/cases/public/index.tsx
@@ -12,6 +12,11 @@ export function plugin(initializerContext: PluginInitializerContext) {
   return new CasesUiPlugin(initializerContext);
 }
 
-export { CasesUiPlugin };
-export * from './plugin';
-export * from './types';
+export type { CasesUiPlugin };
+export type { CasesUiStart } from './types';
+export type { AllCasesProps } from './components/all_cases';
+export type { AllCasesSelectorModalProps } from './components/all_cases/selector_modal';
+export type { CaseViewProps } from './components/case_view';
+export type { ConfigureCasesProps } from './components/configure_cases';
+export type { CreateCaseProps } from './components/create';
+export type { RecentCasesProps } from './components/recent_cases';
diff --git a/x-pack/plugins/cases/public/types.ts b/x-pack/plugins/cases/public/types.ts
index 2193832492aa2..2b31935c3ff97 100644
--- a/x-pack/plugins/cases/public/types.ts
+++ b/x-pack/plugins/cases/public/types.ts
@@ -44,12 +44,42 @@ export interface Owner {
 }
 
 export interface CasesUiStart {
+  /**
+   * Get the all cases table
+   * @param props AllCasesProps
+   * @returns A react component that displays all cases
+   */
   getAllCases: (props: AllCasesProps) => ReactElement<AllCasesProps>;
+  /**
+   * use Modal hook for all cases selector
+   * @param props UseAllCasesSelectorModalProps
+   * @returns A react component that is a modal for selecting a case
+   */
   getAllCasesSelectorModal: (
     props: AllCasesSelectorModalProps
   ) => ReactElement<AllCasesSelectorModalProps>;
+  /**
+   * Get the case view component
+   * @param props CaseViewProps
+   * @returns A react component for viewing a specific case
+   */
   getCaseView: (props: CaseViewProps) => ReactElement<CaseViewProps>;
+  /**
+   * Get the configure case component
+   * @param props ConfigureCasesProps
+   * @returns A react component for configuring a specific case
+   */
   getConfigureCases: (props: ConfigureCasesProps) => ReactElement<ConfigureCasesProps>;
+  /**
+   * Get the create case form
+   * @param props CreateCaseProps
+   * @returns A react component for creating a new case
+   */
   getCreateCase: (props: CreateCaseProps) => ReactElement<CreateCaseProps>;
+  /**
+   * Get the recent cases component
+   * @param props RecentCasesProps
+   * @returns A react component for showing recent cases
+   */
   getRecentCases: (props: RecentCasesProps) => ReactElement<RecentCasesProps>;
 }
diff --git a/x-pack/plugins/enterprise_search/kibana.json b/x-pack/plugins/enterprise_search/kibana.json
index daae8cf57f63d..a7b29a1e6b457 100644
--- a/x-pack/plugins/enterprise_search/kibana.json
+++ b/x-pack/plugins/enterprise_search/kibana.json
@@ -7,5 +7,10 @@
   "optionalPlugins": ["usageCollection", "security", "home", "spaces", "cloud"],
   "server": true,
   "ui": true,
-  "requiredBundles": ["home"]
+  "requiredBundles": ["home"],
+  "owner": {
+    "name": "Enterprise Search",
+    "githubTeam": "enterprise-search-frontend"
+  },
+  "description": "Adds dashboards for discovering and managing Enterprise Search products"
 }
diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/kibana_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/kibana_logic.mock.ts
index ebb6f8c4fe5aa..f2c6ccfacf2bb 100644
--- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/kibana_logic.mock.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/kibana_logic.mock.ts
@@ -7,6 +7,8 @@
 
 import { chartPluginMock } from '../../../../../../../src/plugins/charts/public/mocks';
 
+import { securityMock } from '../../../../../security/public/mocks';
+
 import { mockHistory } from '../react_router/state.mock';
 
 export const mockKibanaValues = {
@@ -18,6 +20,7 @@ export const mockKibanaValues = {
   },
   history: mockHistory,
   navigateToUrl: jest.fn(),
+  security: securityMock.createStart(),
   setBreadcrumbs: jest.fn(),
   setChromeIsVisible: jest.fn(),
   setDocTitle: jest.fn(),
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/engine_assignment_selector.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/engine_assignment_selector.test.tsx
new file mode 100644
index 0000000000000..01c46e6423d70
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/engine_assignment_selector.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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import '../../../__mocks__/react_router';
+import '../../../__mocks__/shallow_useeffect.mock';
+import { DEFAULT_INITIAL_APP_DATA } from '../../../../../common/__mocks__';
+import { setMockActions, setMockValues } from '../../../__mocks__/kea_logic';
+import { engines } from '../../__mocks__/engines.mock';
+
+import React from 'react';
+
+import { waitFor } from '@testing-library/dom';
+import { shallow } from 'enzyme';
+
+import { EuiComboBox, EuiComboBoxOptionOption, EuiRadioGroup } from '@elastic/eui';
+
+import { asRoleMapping } from '../../../shared/role_mapping/__mocks__/roles';
+
+import { EngineAssignmentSelector } from './engine_assignment_selector';
+
+describe('EngineAssignmentSelector', () => {
+  const mockRole = DEFAULT_INITIAL_APP_DATA.appSearch.role;
+  const actions = {
+    initializeRoleMappings: jest.fn(),
+    initializeRoleMapping: jest.fn(),
+    handleSaveMapping: jest.fn(),
+    handleEngineSelectionChange: jest.fn(),
+    handleAccessAllEnginesChange: jest.fn(),
+    handleAttributeValueChange: jest.fn(),
+    handleAttributeSelectorChange: jest.fn(),
+    handleDeleteMapping: jest.fn(),
+    handleRoleChange: jest.fn(),
+    handleAuthProviderChange: jest.fn(),
+    resetState: jest.fn(),
+  };
+
+  const mockValues = {
+    attributes: [],
+    elasticsearchRoles: [],
+    hasAdvancedRoles: true,
+    dataLoading: false,
+    roleType: 'admin',
+    roleMappings: [asRoleMapping],
+    attributeValue: '',
+    attributeName: 'username',
+    availableEngines: engines,
+    selectedEngines: new Set(),
+    accessAllEngines: false,
+    availableAuthProviders: [],
+    multipleAuthProvidersConfig: true,
+    selectedAuthProviders: [],
+    myRole: {
+      availableRoleTypes: mockRole.ability.availableRoleTypes,
+    },
+    roleMappingErrors: [],
+  };
+
+  beforeEach(() => {
+    setMockActions(actions);
+    setMockValues(mockValues);
+  });
+
+  it('renders', () => {
+    setMockValues({ ...mockValues, roleMapping: asRoleMapping });
+    const wrapper = shallow(<EngineAssignmentSelector />);
+
+    expect(wrapper.find(EuiRadioGroup)).toHaveLength(1);
+    expect(wrapper.find(EuiComboBox)).toHaveLength(1);
+  });
+
+  it('sets initial selected state when accessAllEngines is true', () => {
+    setMockValues({ ...mockValues, accessAllEngines: true });
+    const wrapper = shallow(<EngineAssignmentSelector />);
+
+    expect(wrapper.find(EuiRadioGroup).prop('idSelected')).toBe('all');
+  });
+
+  it('handles all/specific engines radio change', () => {
+    const wrapper = shallow(<EngineAssignmentSelector />);
+    const radio = wrapper.find(EuiRadioGroup);
+    radio.simulate('change', { target: { checked: false } });
+
+    expect(actions.handleAccessAllEnginesChange).toHaveBeenCalledWith(false);
+  });
+
+  it('handles engine checkbox click', async () => {
+    const wrapper = shallow(<EngineAssignmentSelector />);
+    await waitFor(() =>
+      ((wrapper.find(EuiComboBox).props() as unknown) as {
+        onChange: (a: EuiComboBoxOptionOption[]) => void;
+      }).onChange([{ label: engines[0].name, value: engines[0].name }])
+    );
+    wrapper.update();
+
+    expect(actions.handleEngineSelectionChange).toHaveBeenCalledWith([engines[0].name]);
+  });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/engine_assignment_selector.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/engine_assignment_selector.tsx
new file mode 100644
index 0000000000000..bb40a1a4fa279
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/engine_assignment_selector.tsx
@@ -0,0 +1,87 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { useActions, useValues } from 'kea';
+
+import { EuiComboBox, EuiFormRow, EuiHorizontalRule, EuiRadioGroup } from '@elastic/eui';
+
+import { RoleOptionLabel } from '../../../shared/role_mapping';
+
+import { roleHasScopedEngines } from '../../utils/role/has_scoped_engines';
+
+import {
+  ENGINE_REQUIRED_ERROR,
+  ALL_ENGINES_LABEL,
+  ALL_ENGINES_DESCRIPTION,
+  SPECIFIC_ENGINES_LABEL,
+  SPECIFIC_ENGINES_DESCRIPTION,
+  ENGINE_ASSIGNMENT_LABEL,
+} from './constants';
+import { RoleMappingsLogic } from './role_mappings_logic';
+
+export const EngineAssignmentSelector: React.FC = () => {
+  const { handleAccessAllEnginesChange, handleEngineSelectionChange } = useActions(
+    RoleMappingsLogic
+  );
+
+  const {
+    accessAllEngines,
+    availableEngines,
+    roleType,
+    selectedEngines,
+    selectedOptions,
+  } = useValues(RoleMappingsLogic);
+
+  const hasEngineAssignment = selectedEngines.size > 0 || accessAllEngines;
+
+  const engineOptions = [
+    {
+      id: 'all',
+      label: <RoleOptionLabel label={ALL_ENGINES_LABEL} description={ALL_ENGINES_DESCRIPTION} />,
+    },
+    {
+      id: 'specific',
+      label: (
+        <RoleOptionLabel
+          label={SPECIFIC_ENGINES_LABEL}
+          description={SPECIFIC_ENGINES_DESCRIPTION}
+        />
+      ),
+    },
+  ];
+
+  return (
+    <>
+      <EuiHorizontalRule />
+      <EuiFormRow>
+        <EuiRadioGroup
+          options={engineOptions}
+          disabled={!roleHasScopedEngines(roleType)}
+          idSelected={accessAllEngines ? 'all' : 'specific'}
+          onChange={(id) => handleAccessAllEnginesChange(id === 'all')}
+          legend={{
+            children: <span>{ENGINE_ASSIGNMENT_LABEL}</span>,
+          }}
+        />
+      </EuiFormRow>
+      <EuiFormRow isInvalid={!hasEngineAssignment} error={[ENGINE_REQUIRED_ERROR]}>
+        <EuiComboBox
+          data-test-subj="enginesSelect"
+          selectedOptions={selectedOptions}
+          options={availableEngines.map(({ name }) => ({ label: name, value: name }))}
+          onChange={(options) => {
+            handleEngineSelectionChange(options.map(({ value }) => value as string));
+          }}
+          fullWidth
+          isDisabled={accessAllEngines || !roleHasScopedEngines(roleType)}
+        />
+      </EuiFormRow>
+    </>
+  );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mapping.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mapping.test.tsx
index 0b7d4255fc323..8932c17367b2c 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mapping.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mapping.test.tsx
@@ -13,16 +13,14 @@ import { engines } from '../../__mocks__/engines.mock';
 
 import React from 'react';
 
-import { waitFor } from '@testing-library/dom';
 import { shallow } from 'enzyme';
 
-import { EuiComboBox, EuiComboBoxOptionOption, EuiRadioGroup } from '@elastic/eui';
-
 import { AttributeSelector, RoleSelector, RoleMappingFlyout } from '../../../shared/role_mapping';
 import { asRoleMapping } from '../../../shared/role_mapping/__mocks__/roles';
 
 import { STANDARD_ROLE_TYPES } from './constants';
 
+import { EngineAssignmentSelector } from './engine_assignment_selector';
 import { RoleMapping } from './role_mapping';
 
 describe('RoleMapping', () => {
@@ -73,6 +71,7 @@ describe('RoleMapping', () => {
 
     expect(wrapper.find(AttributeSelector)).toHaveLength(1);
     expect(wrapper.find(RoleSelector)).toHaveLength(1);
+    expect(wrapper.find(EngineAssignmentSelector)).toHaveLength(1);
   });
 
   it('only passes standard role options for non-advanced roles', () => {
@@ -82,33 +81,6 @@ describe('RoleMapping', () => {
     expect(wrapper.find(RoleSelector).prop('roleOptions')).toHaveLength(STANDARD_ROLE_TYPES.length);
   });
 
-  it('sets initial selected state when accessAllEngines is true', () => {
-    setMockValues({ ...mockValues, accessAllEngines: true });
-    const wrapper = shallow(<RoleMapping />);
-
-    expect(wrapper.find(EuiRadioGroup).prop('idSelected')).toBe('all');
-  });
-
-  it('handles all/specific engines radio change', () => {
-    const wrapper = shallow(<RoleMapping />);
-    const radio = wrapper.find(EuiRadioGroup);
-    radio.simulate('change', { target: { checked: false } });
-
-    expect(actions.handleAccessAllEnginesChange).toHaveBeenCalledWith(false);
-  });
-
-  it('handles engine checkbox click', async () => {
-    const wrapper = shallow(<RoleMapping />);
-    await waitFor(() =>
-      ((wrapper.find(EuiComboBox).props() as unknown) as {
-        onChange: (a: EuiComboBoxOptionOption[]) => void;
-      }).onChange([{ label: engines[0].name, value: engines[0].name }])
-    );
-    wrapper.update();
-
-    expect(actions.handleEngineSelectionChange).toHaveBeenCalledWith([engines[0].name]);
-  });
-
   it('enables flyout when attribute value is valid', () => {
     setMockValues({
       ...mockValues,
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mapping.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mapping.tsx
index 7962734f86e2d..b6a9dd72cfd05 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mapping.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mapping.tsx
@@ -9,47 +9,23 @@ import React from 'react';
 
 import { useActions, useValues } from 'kea';
 
-import {
-  EuiComboBox,
-  EuiForm,
-  EuiFormRow,
-  EuiHorizontalRule,
-  EuiRadioGroup,
-  EuiSpacer,
-} from '@elastic/eui';
+import { EuiForm, EuiSpacer } from '@elastic/eui';
 
-import {
-  AttributeSelector,
-  RoleSelector,
-  RoleOptionLabel,
-  RoleMappingFlyout,
-} from '../../../shared/role_mapping';
+import { AttributeSelector, RoleSelector, RoleMappingFlyout } from '../../../shared/role_mapping';
 import { AppLogic } from '../../app_logic';
 import { AdvanceRoleType } from '../../types';
 
-import { roleHasScopedEngines } from '../../utils/role/has_scoped_engines';
-
-import {
-  ADVANCED_ROLE_TYPES,
-  STANDARD_ROLE_TYPES,
-  ENGINE_REQUIRED_ERROR,
-  ALL_ENGINES_LABEL,
-  ALL_ENGINES_DESCRIPTION,
-  SPECIFIC_ENGINES_LABEL,
-  SPECIFIC_ENGINES_DESCRIPTION,
-  ENGINE_ASSIGNMENT_LABEL,
-} from './constants';
+import { ADVANCED_ROLE_TYPES, STANDARD_ROLE_TYPES } from './constants';
+import { EngineAssignmentSelector } from './engine_assignment_selector';
 import { RoleMappingsLogic } from './role_mappings_logic';
 
 export const RoleMapping: React.FC = () => {
   const { myRole } = useValues(AppLogic);
 
   const {
-    handleAccessAllEnginesChange,
     handleAttributeSelectorChange,
     handleAttributeValueChange,
     handleAuthProviderChange,
-    handleEngineSelectionChange,
     handleRoleChange,
     handleSaveMapping,
     closeRoleMappingFlyout,
@@ -61,7 +37,6 @@ export const RoleMapping: React.FC = () => {
     attributeValue,
     attributes,
     availableAuthProviders,
-    availableEngines,
     elasticsearchRoles,
     hasAdvancedRoles,
     multipleAuthProvidersConfig,
@@ -69,7 +44,6 @@ export const RoleMapping: React.FC = () => {
     roleType,
     selectedEngines,
     selectedAuthProviders,
-    selectedOptions,
     roleMappingErrors,
   } = useValues(RoleMappingsLogic);
 
@@ -90,22 +64,6 @@ export const RoleMapping: React.FC = () => {
     ? [...standardRoleOptions, ...advancedRoleOptions]
     : standardRoleOptions;
 
-  const engineOptions = [
-    {
-      id: 'all',
-      label: <RoleOptionLabel label={ALL_ENGINES_LABEL} description={ALL_ENGINES_DESCRIPTION} />,
-    },
-    {
-      id: 'specific',
-      label: (
-        <RoleOptionLabel
-          label={SPECIFIC_ENGINES_LABEL}
-          description={SPECIFIC_ENGINES_DESCRIPTION}
-        />
-      ),
-    },
-  ];
-
   return (
     <RoleMappingFlyout
       disabled={attributeValueInvalid || !hasEngineAssignment}
@@ -135,35 +93,7 @@ export const RoleMapping: React.FC = () => {
           onChange={handleRoleChange}
           label="Role"
         />
-
-        {hasAdvancedRoles && (
-          <>
-            <EuiHorizontalRule />
-            <EuiFormRow>
-              <EuiRadioGroup
-                options={engineOptions}
-                disabled={!roleHasScopedEngines(roleType)}
-                idSelected={accessAllEngines ? 'all' : 'specific'}
-                onChange={(id) => handleAccessAllEnginesChange(id === 'all')}
-                legend={{
-                  children: <span>{ENGINE_ASSIGNMENT_LABEL}</span>,
-                }}
-              />
-            </EuiFormRow>
-            <EuiFormRow isInvalid={!hasEngineAssignment} error={[ENGINE_REQUIRED_ERROR]}>
-              <EuiComboBox
-                data-test-subj="enginesSelect"
-                selectedOptions={selectedOptions}
-                options={availableEngines.map(({ name }) => ({ label: name, value: name }))}
-                onChange={(options) => {
-                  handleEngineSelectionChange(options.map(({ value }) => value as string));
-                }}
-                fullWidth
-                isDisabled={accessAllEngines || !roleHasScopedEngines(roleType)}
-              />
-            </EuiFormRow>
-          </>
-        )}
+        {hasAdvancedRoles && <EngineAssignmentSelector />}
       </EuiForm>
     </RoleMappingFlyout>
   );
diff --git a/x-pack/plugins/enterprise_search/public/applications/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/index.test.tsx
index 2e0940b9c4af2..cb73686eb4c5b 100644
--- a/x-pack/plugins/enterprise_search/public/applications/index.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/index.test.tsx
@@ -12,6 +12,7 @@ import { getContext } from 'kea';
 import { coreMock } from '../../../../../src/core/public/mocks';
 import { chartPluginMock } from '../../../../../src/plugins/charts/public/mocks';
 import { licensingMock } from '../../../licensing/public/mocks';
+import { securityMock } from '../../../security/public/mocks';
 
 import { AppSearch } from './app_search';
 import { EnterpriseSearch } from './enterprise_search';
@@ -27,6 +28,7 @@ describe('renderApp', () => {
     plugins: {
       licensing: licensingMock.createStart(),
       charts: chartPluginMock.createStartContract(),
+      security: securityMock.createStart(),
     },
   } as any;
   const pluginData = {
diff --git a/x-pack/plugins/enterprise_search/public/applications/index.tsx b/x-pack/plugins/enterprise_search/public/applications/index.tsx
index c2bf77751528a..ba2b28e64b9cf 100644
--- a/x-pack/plugins/enterprise_search/public/applications/index.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/index.tsx
@@ -48,6 +48,7 @@ export const renderApp = (
     cloud: plugins.cloud || {},
     history: params.history,
     navigateToUrl: core.application.navigateToUrl,
+    security: plugins.security || {},
     setBreadcrumbs: core.chrome.setBreadcrumbs,
     setChromeIsVisible: core.chrome.setIsVisible,
     setDocTitle: core.chrome.docTitle.change,
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts
index 2bef7d373f160..9c6db7d09f72c 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts
@@ -13,6 +13,7 @@ import { kea, MakeLogicType } from 'kea';
 import { ApplicationStart, ChromeBreadcrumb } from '../../../../../../../src/core/public';
 import { ChartsPluginStart } from '../../../../../../../src/plugins/charts/public';
 import { CloudSetup } from '../../../../../cloud/public';
+import { SecurityPluginStart } from '../../../../../security/public';
 
 import { HttpLogic } from '../http';
 import { createHref, CreateHrefOptions } from '../react_router_helpers';
@@ -23,6 +24,7 @@ interface KibanaLogicProps {
   cloud: Partial<CloudSetup>;
   charts: ChartsPluginStart;
   navigateToUrl: ApplicationStart['navigateToUrl'];
+  security: Partial<SecurityPluginStart>;
   setBreadcrumbs(crumbs: ChromeBreadcrumb[]): void;
   setChromeIsVisible(isVisible: boolean): void;
   setDocTitle(title: string): void;
@@ -47,6 +49,7 @@ export const KibanaLogic = kea<MakeLogicType<KibanaValues>>({
       },
       {},
     ],
+    security: [props.security || {}, {}],
     setBreadcrumbs: [props.setBreadcrumbs, {}],
     setChromeIsVisible: [props.setChromeIsVisible, {}],
     setDocTitle: [props.setDocTitle, {}],
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts
index be0c860627f79..47d481630510e 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts
@@ -200,3 +200,8 @@ export const ROLE_MAPPINGS_HEADING_BUTTON = i18n.translate(
   'xpack.enterpriseSearch.roleMapping.roleMappingsHeadingButton',
   { defaultMessage: 'Create a new role mapping' }
 );
+
+export const ROLE_MAPPINGS_NO_RESULTS_MESSAGE = i18n.translate(
+  'xpack.enterpriseSearch.roleMapping.noResults.message',
+  { defaultMessage: 'Create a new role mapping' }
+);
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/index.ts
index 0f9362157f50a..b0d10e9692714 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/index.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/index.ts
@@ -11,3 +11,4 @@ export { RoleOptionLabel } from './role_option_label';
 export { RoleSelector } from './role_selector';
 export { RoleMappingFlyout } from './role_mapping_flyout';
 export { RoleMappingsHeading } from './role_mappings_heading';
+export { UsersAndRolesRowActions } from './users_and_roles_row_actions';
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.test.tsx
index 5ec84db478bc3..156b52a4016c3 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.test.tsx
@@ -9,13 +9,14 @@ import { wsRoleMapping, asRoleMapping } from './__mocks__/roles';
 
 import React from 'react';
 
-import { shallow } from 'enzyme';
+import { mount } from 'enzyme';
 
-import { EuiFieldSearch, EuiTableRow } from '@elastic/eui';
+import { EuiInMemoryTable, EuiTableHeaderCell } from '@elastic/eui';
 
 import { ALL_LABEL, ANY_AUTH_PROVIDER_OPTION_LABEL } from './constants';
 
 import { RoleMappingsTable } from './role_mappings_table';
+import { UsersAndRolesRowActions } from './users_and_roles_row_actions';
 
 describe('RoleMappingsTable', () => {
   const initializeRoleMapping = jest.fn();
@@ -41,55 +42,44 @@ describe('RoleMappingsTable', () => {
     handleDeleteMapping,
   };
 
-  it('renders', () => {
-    const wrapper = shallow(<RoleMappingsTable {...props} />);
+  it('renders with "shouldShowAuthProvider" true', () => {
+    const wrapper = mount(<RoleMappingsTable {...props} />);
 
-    expect(wrapper.find(EuiFieldSearch)).toHaveLength(1);
-    expect(wrapper.find(EuiTableRow)).toHaveLength(1);
+    expect(wrapper.find(EuiInMemoryTable)).toHaveLength(1);
+    expect(wrapper.find(EuiTableHeaderCell)).toHaveLength(6);
   });
 
-  it('renders auth provider display names', () => {
-    const wrapper = shallow(<RoleMappingsTable {...props} />);
+  it('renders with "shouldShowAuthProvider" false', () => {
+    const wrapper = mount(<RoleMappingsTable {...props} shouldShowAuthProvider={false} />);
 
-    expect(wrapper.find('[data-test-subj="AuthProviderDisplay"]').prop('children')).toEqual(
-      `${ANY_AUTH_PROVIDER_OPTION_LABEL}, other_auth`
-    );
+    expect(wrapper.find(EuiInMemoryTable)).toHaveLength(1);
+    expect(wrapper.find(EuiTableHeaderCell)).toHaveLength(5);
   });
 
-  it('handles input change', () => {
-    const wrapper = shallow(<RoleMappingsTable {...props} />);
-    const input = wrapper.find(EuiFieldSearch);
-    const value = 'Query';
-    input.simulate('change', { target: { value } });
+  it('renders auth provider display names', () => {
+    const wrapper = mount(<RoleMappingsTable {...props} />);
 
-    expect(wrapper.find(EuiTableRow)).toHaveLength(0);
+    expect(wrapper.find('[data-test-subj="AuthProviderDisplayValue"]').prop('children')).toEqual(
+      `${ANY_AUTH_PROVIDER_OPTION_LABEL}, other_auth`
+    );
   });
 
   it('handles manage click', () => {
-    const wrapper = shallow(<RoleMappingsTable {...props} />);
-    wrapper.find('[data-test-subj="ManageButton"]').simulate('click');
+    const wrapper = mount(<RoleMappingsTable {...props} />);
+    wrapper.find(UsersAndRolesRowActions).prop('onManageClick')();
 
     expect(initializeRoleMapping).toHaveBeenCalled();
   });
 
   it('handles delete click', () => {
-    const wrapper = shallow(<RoleMappingsTable {...props} />);
-    wrapper.find('[data-test-subj="DeleteButton"]').simulate('click');
+    const wrapper = mount(<RoleMappingsTable {...props} />);
+    wrapper.find(UsersAndRolesRowActions).prop('onDeleteClick')();
 
     expect(handleDeleteMapping).toHaveBeenCalled();
   });
 
-  it('handles input change with special chars', () => {
-    const wrapper = shallow(<RoleMappingsTable {...props} />);
-    const input = wrapper.find(EuiFieldSearch);
-    const value = '*//username';
-    input.simulate('change', { target: { value } });
-
-    expect(wrapper.find(EuiTableRow)).toHaveLength(1);
-  });
-
   it('shows default message when "accessAllEngines" is true', () => {
-    const wrapper = shallow(
+    const wrapper = mount(
       <RoleMappingsTable {...props} roleMappings={[asRoleMapping as any]} accessItemKey="engines" />
     );
 
@@ -100,7 +90,7 @@ describe('RoleMappingsTable', () => {
     const noItemsRoleMapping = { ...asRoleMapping, engines: [] };
     noItemsRoleMapping.accessAllEngines = false;
 
-    const wrapper = shallow(
+    const wrapper = mount(
       <RoleMappingsTable
         {...props}
         roleMappings={[noItemsRoleMapping as any]}
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.tsx
index f185e9ffb418e..82284be0907fb 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/role_mappings_table.tsx
@@ -5,26 +5,12 @@
  * 2.0.
  */
 
-import React, { Fragment, useState } from 'react';
+import React, { Fragment } from 'react';
 
-import {
-  EuiButtonIcon,
-  EuiFieldSearch,
-  EuiIconTip,
-  EuiSpacer,
-  EuiTable,
-  EuiTableBody,
-  EuiTableHeader,
-  EuiTableHeaderCell,
-  EuiTableRow,
-  EuiTableRowCell,
-  EuiTextColor,
-} from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
+import { EuiTextColor, EuiInMemoryTable, EuiBasicTableColumn } from '@elastic/eui';
 
 import { ASRoleMapping } from '../../app_search/types';
 import { WSRoleMapping } from '../../workplace_search/types';
-import { MANAGE_BUTTON_LABEL, DELETE_BUTTON_LABEL } from '../constants';
 import { RoleRules } from '../types';
 
 import './role_mappings_table.scss';
@@ -38,7 +24,9 @@ import {
   EXTERNAL_ATTRIBUTE_LABEL,
   ATTRIBUTE_VALUE_LABEL,
   FILTER_ROLE_MAPPINGS_PLACEHOLDER,
+  ROLE_MAPPINGS_NO_RESULTS_MESSAGE,
 } from './constants';
+import { UsersAndRolesRowActions } from './users_and_roles_row_actions';
 
 interface AccessItem {
   name: string;
@@ -58,8 +46,6 @@ interface Props {
   handleDeleteMapping(roleMappingId: string): void;
 }
 
-const MAX_CELL_WIDTH = 24;
-
 const noItemsPlaceholder = <EuiTextColor color="subdued">&mdash;</EuiTextColor>;
 
 const getAuthProviderDisplayValue = (authProvider: string) =>
@@ -73,114 +59,104 @@ export const RoleMappingsTable: React.FC<Props> = ({
   initializeRoleMapping,
   handleDeleteMapping,
 }) => {
-  const [filterValue, updateValue] = useState('');
+  const getFirstAttributeName = (rules: RoleRules): string => Object.entries(rules)[0][0];
+  const getFirstAttributeValue = (rules: RoleRules): string => Object.entries(rules)[0][1];
 
   // This is needed because App Search has `engines` and Workplace Search has `groups`.
-  const standardizeRoleMapping = (roleMappings as SharedRoleMapping[]).map((rm) => {
+  const standardizedRoleMappings = (roleMappings as SharedRoleMapping[]).map((rm) => {
     const _rm = { ...rm } as SharedRoleMapping;
     _rm.accessItems = rm[accessItemKey];
     return _rm;
-  });
-
-  const filterResults = (result: SharedRoleMapping) => {
-    // Filter out non-alphanumeric characters, except for underscores, hyphens, and spaces
-    const sanitizedValue = filterValue.replace(/[^\w\s-]/g, '');
-    const values = Object.values(result);
-    const regexp = new RegExp(sanitizedValue, 'i');
-    return values.filter((x) => regexp.test(x)).length > 0;
+  }) as SharedRoleMapping[];
+
+  const attributeNameCol: EuiBasicTableColumn<SharedRoleMapping> = {
+    field: 'attribute',
+    name: EXTERNAL_ATTRIBUTE_LABEL,
+    render: (_, { rules }: SharedRoleMapping) => getFirstAttributeName(rules),
   };
 
-  const filteredResults = standardizeRoleMapping.filter(filterResults);
-  const getFirstAttributeName = (rules: RoleRules): string => Object.entries(rules)[0][0];
-  const getFirstAttributeValue = (rules: RoleRules): string => Object.entries(rules)[0][1];
+  const attributeValueCol: EuiBasicTableColumn<SharedRoleMapping> = {
+    field: 'attributeValue',
+    name: ATTRIBUTE_VALUE_LABEL,
+    render: (_, { rules }: SharedRoleMapping) => getFirstAttributeValue(rules),
+  };
 
-  const rowActions = (id: string) => (
-    <>
-      <EuiButtonIcon
-        onClick={() => initializeRoleMapping(id)}
-        iconType="pencil"
-        aria-label={MANAGE_BUTTON_LABEL}
-        data-test-subj="ManageButton"
-      />{' '}
-      <EuiButtonIcon
-        onClick={() => handleDeleteMapping(id)}
-        iconType="trash"
-        aria-label={DELETE_BUTTON_LABEL}
-        data-test-subj="DeleteButton"
+  const roleCol: EuiBasicTableColumn<SharedRoleMapping> = {
+    field: 'roleType',
+    name: ROLE_LABEL,
+    render: (_, { rules }: SharedRoleMapping) => getFirstAttributeValue(rules),
+  };
+
+  const accessItemsCol: EuiBasicTableColumn<SharedRoleMapping> = {
+    field: 'accessItems',
+    name: accessHeader,
+    render: (_, { accessAllEngines, accessItems }: SharedRoleMapping) => (
+      <span data-test-subj="AccessItemsList">
+        {accessAllEngines ? (
+          ALL_LABEL
+        ) : (
+          <>
+            {accessItems.length === 0
+              ? noItemsPlaceholder
+              : accessItems.map(({ name }) => (
+                  <Fragment key={name}>
+                    {name}
+                    <br />
+                  </Fragment>
+                ))}
+          </>
+        )}
+      </span>
+    ),
+  };
+
+  const authProviderCol: EuiBasicTableColumn<SharedRoleMapping> = {
+    field: 'authProvider',
+    name: AUTH_PROVIDER_LABEL,
+    render: (_, { authProvider }: SharedRoleMapping) => (
+      <span data-test-subj="AuthProviderDisplayValue">
+        {authProvider.map(getAuthProviderDisplayValue).join(', ')}
+      </span>
+    ),
+  };
+
+  const actionsCol: EuiBasicTableColumn<SharedRoleMapping> = {
+    field: 'id',
+    name: '',
+    align: 'right',
+    render: (_, { id }: SharedRoleMapping) => (
+      <UsersAndRolesRowActions
+        onManageClick={() => initializeRoleMapping(id)}
+        onDeleteClick={() => handleDeleteMapping(id)}
       />
-    </>
-  );
+    ),
+  };
 
+  const columns = shouldShowAuthProvider
+    ? [attributeNameCol, attributeValueCol, roleCol, accessItemsCol, authProviderCol, actionsCol]
+    : [attributeNameCol, attributeValueCol, roleCol, accessItemsCol, actionsCol];
+
+  const pagination = {
+    hidePerPageOptions: true,
+  };
+
+  const search = {
+    box: {
+      incremental: true,
+      fullWidth: false,
+      placeholder: FILTER_ROLE_MAPPINGS_PLACEHOLDER,
+      'data-test-subj': 'RoleMappingsTableSearchInput',
+    },
+  };
   return (
-    <>
-      <EuiFieldSearch
-        value={filterValue}
-        placeholder={FILTER_ROLE_MAPPINGS_PLACEHOLDER}
-        onChange={(e) => updateValue(e.target.value)}
-      />
-      <EuiSpacer />
-      {filteredResults.length > 0 ? (
-        <EuiTable className="roleMappingsTable">
-          <EuiTableHeader>
-            <EuiTableHeaderCell>{EXTERNAL_ATTRIBUTE_LABEL}</EuiTableHeaderCell>
-            <EuiTableHeaderCell>{ATTRIBUTE_VALUE_LABEL}</EuiTableHeaderCell>
-            <EuiTableHeaderCell>{ROLE_LABEL}</EuiTableHeaderCell>
-            <EuiTableHeaderCell>{accessHeader}</EuiTableHeaderCell>
-            {shouldShowAuthProvider && (
-              <EuiTableHeaderCell>{AUTH_PROVIDER_LABEL}</EuiTableHeaderCell>
-            )}
-            <EuiTableHeaderCell />
-          </EuiTableHeader>
-          <EuiTableBody>
-            {filteredResults.map(
-              ({ id, authProvider, rules, roleType, accessAllEngines, accessItems, toolTip }) => (
-                <EuiTableRow key={id}>
-                  <EuiTableRowCell>{getFirstAttributeName(rules)}</EuiTableRowCell>
-                  <EuiTableRowCell style={{ maxWidth: MAX_CELL_WIDTH }}>
-                    {getFirstAttributeValue(rules)}
-                  </EuiTableRowCell>
-                  <EuiTableRowCell>{roleType}</EuiTableRowCell>
-                  <EuiTableRowCell
-                    data-test-subj="AccessItemsList"
-                    style={{ maxWidth: MAX_CELL_WIDTH }}
-                  >
-                    {accessAllEngines ? (
-                      ALL_LABEL
-                    ) : (
-                      <>
-                        {accessItems.length === 0
-                          ? noItemsPlaceholder
-                          : accessItems.map(({ name }) => (
-                              <Fragment key={name}>
-                                {name}
-                                <br />
-                              </Fragment>
-                            ))}
-                      </>
-                    )}
-                  </EuiTableRowCell>
-                  {shouldShowAuthProvider && (
-                    <EuiTableRowCell data-test-subj="AuthProviderDisplay">
-                      {authProvider.map(getAuthProviderDisplayValue).join(', ')}
-                    </EuiTableRowCell>
-                  )}
-                  <EuiTableRowCell align="right">
-                    {id && rowActions(id)}
-                    {toolTip && <EuiIconTip position="left" content={toolTip.content} />}
-                  </EuiTableRowCell>
-                </EuiTableRow>
-              )
-            )}
-          </EuiTableBody>
-        </EuiTable>
-      ) : (
-        <p>
-          {i18n.translate('xpack.enterpriseSearch.roleMapping.moResults.message', {
-            defaultMessage: "No results found for '{filterValue}'",
-            values: { filterValue },
-          })}
-        </p>
-      )}
-    </>
+    <EuiInMemoryTable
+      data-test-subj="RoleMappingsTable"
+      columns={columns}
+      items={standardizedRoleMappings}
+      search={search}
+      pagination={pagination}
+      message={ROLE_MAPPINGS_NO_RESULTS_MESSAGE}
+      responsive={false}
+    />
   );
 };
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/users_and_roles_row_actions.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/users_and_roles_row_actions.test.tsx
new file mode 100644
index 0000000000000..dbb47b50d4066
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/users_and_roles_row_actions.test.tsx
@@ -0,0 +1,46 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { shallow } from 'enzyme';
+
+import { EuiButtonIcon } from '@elastic/eui';
+
+import { UsersAndRolesRowActions } from './users_and_roles_row_actions';
+
+describe('UsersAndRolesRowActions', () => {
+  const onManageClick = jest.fn();
+  const onDeleteClick = jest.fn();
+
+  const props = {
+    onManageClick,
+    onDeleteClick,
+  };
+
+  it('renders', () => {
+    const wrapper = shallow(<UsersAndRolesRowActions {...props} />);
+
+    expect(wrapper.find(EuiButtonIcon)).toHaveLength(2);
+  });
+
+  it('handles manage click', () => {
+    const wrapper = shallow(<UsersAndRolesRowActions {...props} />);
+    const button = wrapper.find(EuiButtonIcon).first();
+    button.simulate('click');
+
+    expect(onManageClick).toHaveBeenCalled();
+  });
+
+  it('handles delete click', () => {
+    const wrapper = shallow(<UsersAndRolesRowActions {...props} />);
+    const button = wrapper.find(EuiButtonIcon).last();
+    button.simulate('click');
+
+    expect(onDeleteClick).toHaveBeenCalled();
+  });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/users_and_roles_row_actions.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/users_and_roles_row_actions.tsx
new file mode 100644
index 0000000000000..3d956c0aabd68
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/users_and_roles_row_actions.tsx
@@ -0,0 +1,24 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { EuiButtonIcon } from '@elastic/eui';
+
+import { MANAGE_BUTTON_LABEL, DELETE_BUTTON_LABEL } from '../constants';
+
+interface Props {
+  onManageClick(): void;
+  onDeleteClick(): void;
+}
+
+export const UsersAndRolesRowActions: React.FC<Props> = ({ onManageClick, onDeleteClick }) => (
+  <>
+    <EuiButtonIcon onClick={onManageClick} iconType="pencil" aria-label={MANAGE_BUTTON_LABEL} />{' '}
+    <EuiButtonIcon onClick={onDeleteClick} iconType="trash" aria-label={DELETE_BUTTON_LABEL} />
+  </>
+);
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/account_header/account_header.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/account_header/account_header.tsx
index 92a936fcdbefe..b1e190edade2b 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/account_header/account_header.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/account_header/account_header.tsx
@@ -27,7 +27,7 @@ import { getWorkplaceSearchUrl } from '../../../../shared/enterprise_search_url'
 import { EuiButtonEmptyTo } from '../../../../shared/react_router_helpers';
 import { AppLogic } from '../../../app_logic';
 import { WORKPLACE_SEARCH_TITLE, ACCOUNT_NAV } from '../../../constants';
-import { PERSONAL_SOURCES_PATH, LOGOUT_ROUTE, KIBANA_ACCOUNT_ROUTE } from '../../../routes';
+import { PERSONAL_SOURCES_PATH, LOGOUT_ROUTE, PERSONAL_SETTINGS_PATH } from '../../../routes';
 
 export const AccountHeader: React.FC = () => {
   const [isPopoverOpen, setPopover] = useState(false);
@@ -44,8 +44,7 @@ export const AccountHeader: React.FC = () => {
 
   const accountNavItems = [
     <EuiContextMenuItem key="accountSettings">
-      {/* TODO: Once auth is completed, we need to have non-admins redirect to the self-hosted form */}
-      <EuiButtonEmpty href={KIBANA_ACCOUNT_ROUTE}>{ACCOUNT_NAV.SETTINGS}</EuiButtonEmpty>
+      <EuiButtonEmptyTo to={PERSONAL_SETTINGS_PATH}>{ACCOUNT_NAV.SETTINGS}</EuiButtonEmptyTo>
     </EuiContextMenuItem>,
     <EuiContextMenuItem key="logout">
       <EuiButtonEmpty href={LOGOUT_ROUTE}>{ACCOUNT_NAV.LOGOUT}</EuiButtonEmpty>
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx
index ba5fb7c9d377d..0fc8a6e7c7c0d 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx
@@ -28,7 +28,9 @@ import {
   ORG_SETTINGS_PATH,
   ROLE_MAPPINGS_PATH,
   SECURITY_PATH,
+  PERSONAL_SETTINGS_PATH,
 } from './routes';
+import { AccountSettings } from './views/account_settings';
 import { SourcesRouter } from './views/content_sources';
 import { SourceAdded } from './views/content_sources/components/source_added';
 import { SourceSubNav } from './views/content_sources/components/source_sub_nav';
@@ -103,6 +105,11 @@ export const WorkplaceSearchConfigured: React.FC<InitialAppData> = (props) => {
           <SourcesRouter />
         </PrivateSourcesLayout>
       </Route>
+      <Route path={PERSONAL_SETTINGS_PATH}>
+        <PrivateSourcesLayout restrictWidth readOnlyMode={readOnlyMode}>
+          <AccountSettings />
+        </PrivateSourcesLayout>
+      </Route>
       <Route path={SOURCES_PATH}>
         <Layout
           navigation={<WorkplaceSearchNav sourcesSubNav={showSourcesSubnav && <SourceSubNav />} />}
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts
index 5e5d6e2c82b31..1fe8019c4b364 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts
@@ -13,7 +13,6 @@ export const SETUP_GUIDE_PATH = '/setup_guide';
 
 export const NOT_FOUND_PATH = '/404';
 export const LOGOUT_ROUTE = '/logout';
-export const KIBANA_ACCOUNT_ROUTE = '/security/account';
 
 export const LEAVE_FEEDBACK_EMAIL = 'support@elastic.co';
 export const LEAVE_FEEDBACK_URL = `mailto:${LEAVE_FEEDBACK_EMAIL}?Subject=Elastic%20Workplace%20Search%20Feedback`;
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx
new file mode 100644
index 0000000000000..e28faaeec8993
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx
@@ -0,0 +1,39 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { useState, useEffect, useMemo } from 'react';
+
+import { useValues } from 'kea';
+
+import type { AuthenticatedUser } from '../../../../../../security/public';
+import { KibanaLogic } from '../../../shared/kibana/kibana_logic';
+
+export const AccountSettings: React.FC = () => {
+  const { security } = useValues(KibanaLogic);
+
+  const [currentUser, setCurrentUser] = useState<AuthenticatedUser | null>(null);
+
+  useEffect(() => {
+    security!.authc!.getCurrentUser().then(setCurrentUser);
+  }, [security.authc]);
+
+  const PersonalInfo = useMemo(() => security!.uiApi!.components.getPersonalInfo, [security.uiApi]);
+  const ChangePassword = useMemo(() => security!.uiApi!.components.getChangePassword, [
+    security.uiApi,
+  ]);
+
+  if (!currentUser) {
+    return null;
+  }
+
+  return (
+    <>
+      <PersonalInfo user={currentUser} />
+      <ChangePassword user={currentUser} />
+    </>
+  );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/index.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/index.ts
new file mode 100644
index 0000000000000..016b8f721aea4
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/index.ts
@@ -0,0 +1,8 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export { AccountSettings } from './account_settings';
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/group_assignment_selector.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/group_assignment_selector.test.tsx
new file mode 100644
index 0000000000000..94c21f3b5524f
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/group_assignment_selector.test.tsx
@@ -0,0 +1,113 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import '../../../__mocks__/react_router';
+import '../../../__mocks__/shallow_useeffect.mock';
+import { setMockActions, setMockValues } from '../../../__mocks__/kea_logic';
+
+import React from 'react';
+
+import { waitFor } from '@testing-library/dom';
+import { shallow } from 'enzyme';
+
+import { EuiComboBox, EuiComboBoxOptionOption, EuiRadioGroup } from '@elastic/eui';
+
+import { wsRoleMapping } from '../../../shared/role_mapping/__mocks__/roles';
+
+import { GroupAssignmentSelector } from './group_assignment_selector';
+
+describe('GroupAssignmentSelector', () => {
+  const initializeRoleMappings = jest.fn();
+  const initializeRoleMapping = jest.fn();
+  const handleSaveMapping = jest.fn();
+  const handleGroupSelectionChange = jest.fn();
+  const handleAllGroupsSelectionChange = jest.fn();
+  const handleAttributeValueChange = jest.fn();
+  const handleAttributeSelectorChange = jest.fn();
+  const handleDeleteMapping = jest.fn();
+  const handleRoleChange = jest.fn();
+  const handleAuthProviderChange = jest.fn();
+  const resetState = jest.fn();
+  const groups = [
+    {
+      name: 'Group 1',
+      id: 'g1',
+    },
+    {
+      name: 'Group 2',
+      id: 'g2',
+    },
+  ];
+  const mockValues = {
+    attributes: [],
+    elasticsearchRoles: [],
+    dataLoading: false,
+    roleType: 'admin',
+    roleMappings: [wsRoleMapping],
+    attributeValue: '',
+    attributeName: 'username',
+    availableGroups: groups,
+    selectedGroups: new Set(),
+    includeInAllGroups: false,
+    availableAuthProviders: [],
+    multipleAuthProvidersConfig: true,
+    selectedAuthProviders: [],
+    roleMappingErrors: [],
+  };
+
+  beforeEach(() => {
+    setMockActions({
+      initializeRoleMappings,
+      initializeRoleMapping,
+      handleSaveMapping,
+      handleGroupSelectionChange,
+      handleAllGroupsSelectionChange,
+      handleAttributeValueChange,
+      handleAttributeSelectorChange,
+      handleDeleteMapping,
+      handleRoleChange,
+      handleAuthProviderChange,
+      resetState,
+    });
+    setMockValues(mockValues);
+  });
+
+  it('renders', () => {
+    setMockValues({ ...mockValues, GroupAssignmentSelector: wsRoleMapping });
+    const wrapper = shallow(<GroupAssignmentSelector />);
+
+    expect(wrapper.find(EuiRadioGroup)).toHaveLength(1);
+    expect(wrapper.find(EuiComboBox)).toHaveLength(1);
+  });
+
+  it('sets initial selected state when includeInAllGroups is true', () => {
+    setMockValues({ ...mockValues, includeInAllGroups: true });
+    const wrapper = shallow(<GroupAssignmentSelector />);
+
+    expect(wrapper.find(EuiRadioGroup).prop('idSelected')).toBe('all');
+  });
+
+  it('handles all/specific groups radio change', () => {
+    const wrapper = shallow(<GroupAssignmentSelector />);
+    const radio = wrapper.find(EuiRadioGroup);
+    radio.simulate('change', { target: { checked: false } });
+
+    expect(handleAllGroupsSelectionChange).toHaveBeenCalledWith(false);
+  });
+
+  it('handles group checkbox click', async () => {
+    const wrapper = shallow(<GroupAssignmentSelector />);
+    await waitFor(() =>
+      ((wrapper.find(EuiComboBox).props() as unknown) as {
+        onChange: (a: EuiComboBoxOptionOption[]) => void;
+      }).onChange([{ label: groups[0].name, value: groups[0].name }])
+    );
+    wrapper.update();
+
+    expect(handleGroupSelectionChange).toHaveBeenCalledWith([groups[0].name]);
+  });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/group_assignment_selector.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/group_assignment_selector.tsx
new file mode 100644
index 0000000000000..b53b092eced2d
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/group_assignment_selector.tsx
@@ -0,0 +1,78 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { useActions, useValues } from 'kea';
+
+import { EuiComboBox, EuiFormRow, EuiHorizontalRule, EuiRadioGroup } from '@elastic/eui';
+
+import { RoleOptionLabel } from '../../../shared/role_mapping';
+
+import {
+  GROUP_ASSIGNMENT_INVALID_ERROR,
+  GROUP_ASSIGNMENT_LABEL,
+  ALL_GROUPS_LABEL,
+  ALL_GROUPS_DESCRIPTION,
+  SPECIFIC_GROUPS_LABEL,
+  SPECIFIC_GROUPS_DESCRIPTION,
+} from './constants';
+
+import { RoleMappingsLogic } from './role_mappings_logic';
+
+export const GroupAssignmentSelector: React.FC = () => {
+  const { handleAllGroupsSelectionChange, handleGroupSelectionChange } = useActions(
+    RoleMappingsLogic
+  );
+
+  const { includeInAllGroups, availableGroups, selectedGroups, selectedOptions } = useValues(
+    RoleMappingsLogic
+  );
+
+  const hasGroupAssignment = selectedGroups.size > 0 || includeInAllGroups;
+
+  const groupOptions = [
+    {
+      id: 'all',
+      label: <RoleOptionLabel label={ALL_GROUPS_LABEL} description={ALL_GROUPS_DESCRIPTION} />,
+    },
+    {
+      id: 'specific',
+      label: (
+        <RoleOptionLabel label={SPECIFIC_GROUPS_LABEL} description={SPECIFIC_GROUPS_DESCRIPTION} />
+      ),
+    },
+  ];
+
+  return (
+    <>
+      <EuiHorizontalRule />
+      <EuiFormRow>
+        <EuiRadioGroup
+          options={groupOptions}
+          idSelected={includeInAllGroups ? 'all' : 'specific'}
+          onChange={(id) => handleAllGroupsSelectionChange(id === 'all')}
+          legend={{
+            children: <span>{GROUP_ASSIGNMENT_LABEL}</span>,
+          }}
+        />
+      </EuiFormRow>
+      <EuiFormRow isInvalid={!hasGroupAssignment} error={[GROUP_ASSIGNMENT_INVALID_ERROR]}>
+        <EuiComboBox
+          data-test-subj="groupsSelect"
+          selectedOptions={selectedOptions}
+          options={availableGroups.map(({ name, id }) => ({ label: name, value: id }))}
+          onChange={(options) => {
+            handleGroupSelectionChange(options.map(({ value }) => value as string));
+          }}
+          fullWidth
+          isDisabled={includeInAllGroups}
+        />
+      </EuiFormRow>
+    </>
+  );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mapping.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mapping.test.tsx
index 619a931864500..d0f88984bd8c7 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mapping.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mapping.test.tsx
@@ -11,14 +11,12 @@ import { setMockActions, setMockValues } from '../../../__mocks__/kea_logic';
 
 import React from 'react';
 
-import { waitFor } from '@testing-library/dom';
 import { shallow } from 'enzyme';
 
-import { EuiComboBox, EuiComboBoxOptionOption, EuiRadioGroup } from '@elastic/eui';
-
 import { AttributeSelector, RoleSelector, RoleMappingFlyout } from '../../../shared/role_mapping';
 import { wsRoleMapping } from '../../../shared/role_mapping/__mocks__/roles';
 
+import { GroupAssignmentSelector } from './group_assignment_selector';
 import { RoleMapping } from './role_mapping';
 
 describe('RoleMapping', () => {
@@ -83,33 +81,7 @@ describe('RoleMapping', () => {
 
     expect(wrapper.find(AttributeSelector)).toHaveLength(1);
     expect(wrapper.find(RoleSelector)).toHaveLength(1);
-  });
-
-  it('sets initial selected state when includeInAllGroups is true', () => {
-    setMockValues({ ...mockValues, includeInAllGroups: true });
-    const wrapper = shallow(<RoleMapping />);
-
-    expect(wrapper.find(EuiRadioGroup).prop('idSelected')).toBe('all');
-  });
-
-  it('handles all/specific groups radio change', () => {
-    const wrapper = shallow(<RoleMapping />);
-    const radio = wrapper.find(EuiRadioGroup);
-    radio.simulate('change', { target: { checked: false } });
-
-    expect(handleAllGroupsSelectionChange).toHaveBeenCalledWith(false);
-  });
-
-  it('handles group checkbox click', async () => {
-    const wrapper = shallow(<RoleMapping />);
-    await waitFor(() =>
-      ((wrapper.find(EuiComboBox).props() as unknown) as {
-        onChange: (a: EuiComboBoxOptionOption[]) => void;
-      }).onChange([{ label: groups[0].name, value: groups[0].name }])
-    );
-    wrapper.update();
-
-    expect(handleGroupSelectionChange).toHaveBeenCalledWith([groups[0].name]);
+    expect(wrapper.find(GroupAssignmentSelector)).toHaveLength(1);
   });
 
   it('enables flyout when attribute value is valid', () => {
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mapping.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mapping.tsx
index e2f24ce392c39..cc773895bff1c 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mapping.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mapping.tsx
@@ -9,35 +9,15 @@ import React from 'react';
 
 import { useActions, useValues } from 'kea';
 
-import {
-  EuiComboBox,
-  EuiForm,
-  EuiFormRow,
-  EuiHorizontalRule,
-  EuiRadioGroup,
-  EuiSpacer,
-} from '@elastic/eui';
+import { EuiForm, EuiSpacer } from '@elastic/eui';
 
-import {
-  AttributeSelector,
-  RoleSelector,
-  RoleOptionLabel,
-  RoleMappingFlyout,
-} from '../../../shared/role_mapping';
+import { AttributeSelector, RoleSelector, RoleMappingFlyout } from '../../../shared/role_mapping';
 
 import { Role } from '../../types';
 
-import {
-  ADMIN_ROLE_TYPE_DESCRIPTION,
-  USER_ROLE_TYPE_DESCRIPTION,
-  GROUP_ASSIGNMENT_INVALID_ERROR,
-  GROUP_ASSIGNMENT_LABEL,
-  ALL_GROUPS_LABEL,
-  ALL_GROUPS_DESCRIPTION,
-  SPECIFIC_GROUPS_LABEL,
-  SPECIFIC_GROUPS_DESCRIPTION,
-} from './constants';
+import { ADMIN_ROLE_TYPE_DESCRIPTION, USER_ROLE_TYPE_DESCRIPTION } from './constants';
 
+import { GroupAssignmentSelector } from './group_assignment_selector';
 import { RoleMappingsLogic } from './role_mappings_logic';
 
 interface RoleType {
@@ -56,24 +36,9 @@ const roleOptions = [
   },
 ] as RoleType[];
 
-const groupOptions = [
-  {
-    id: 'all',
-    label: <RoleOptionLabel label={ALL_GROUPS_LABEL} description={ALL_GROUPS_DESCRIPTION} />,
-  },
-  {
-    id: 'specific',
-    label: (
-      <RoleOptionLabel label={SPECIFIC_GROUPS_LABEL} description={SPECIFIC_GROUPS_DESCRIPTION} />
-    ),
-  },
-];
-
 export const RoleMapping: React.FC = () => {
   const {
     handleSaveMapping,
-    handleGroupSelectionChange,
-    handleAllGroupsSelectionChange,
     handleAttributeValueChange,
     handleAttributeSelectorChange,
     handleRoleChange,
@@ -87,13 +52,11 @@ export const RoleMapping: React.FC = () => {
     roleType,
     attributeValue,
     attributeName,
-    availableGroups,
     selectedGroups,
     includeInAllGroups,
     availableAuthProviders,
     multipleAuthProvidersConfig,
     selectedAuthProviders,
-    selectedOptions,
     roleMapping,
     roleMappingErrors,
   } = useValues(RoleMappingsLogic);
@@ -132,29 +95,7 @@ export const RoleMapping: React.FC = () => {
           onChange={handleRoleChange}
           label="Role"
         />
-        <EuiHorizontalRule />
-        <EuiFormRow>
-          <EuiRadioGroup
-            options={groupOptions}
-            idSelected={includeInAllGroups ? 'all' : 'specific'}
-            onChange={(id) => handleAllGroupsSelectionChange(id === 'all')}
-            legend={{
-              children: <span>{GROUP_ASSIGNMENT_LABEL}</span>,
-            }}
-          />
-        </EuiFormRow>
-        <EuiFormRow isInvalid={!hasGroupAssignment} error={[GROUP_ASSIGNMENT_INVALID_ERROR]}>
-          <EuiComboBox
-            data-test-subj="groupsSelect"
-            selectedOptions={selectedOptions}
-            options={availableGroups.map(({ name, id }) => ({ label: name, value: id }))}
-            onChange={(options) => {
-              handleGroupSelectionChange(options.map(({ value }) => value as string));
-            }}
-            fullWidth
-            isDisabled={includeInAllGroups}
-          />
-        </EuiFormRow>
+        <GroupAssignmentSelector />
       </EuiForm>
     </RoleMappingFlyout>
   );
diff --git a/x-pack/plugins/enterprise_search/public/plugin.ts b/x-pack/plugins/enterprise_search/public/plugin.ts
index e402d233da58d..6e521efc369df 100644
--- a/x-pack/plugins/enterprise_search/public/plugin.ts
+++ b/x-pack/plugins/enterprise_search/public/plugin.ts
@@ -21,6 +21,7 @@ import {
 } from '../../../../src/plugins/home/public';
 import { CloudSetup } from '../../cloud/public';
 import { LicensingPluginStart } from '../../licensing/public';
+import { SecurityPluginSetup, SecurityPluginStart } from '../../security/public';
 
 import {
   APP_SEARCH_PLUGIN,
@@ -42,11 +43,13 @@ export interface ClientData extends InitialAppData {
 interface PluginsSetup {
   cloud?: CloudSetup;
   home?: HomePublicPluginSetup;
+  security?: SecurityPluginSetup;
 }
 export interface PluginsStart {
   cloud?: CloudSetup;
   licensing: LicensingPluginStart;
   charts: ChartsPluginStart;
+  security?: SecurityPluginStart;
 }
 
 export class EnterpriseSearchPlugin implements Plugin {
diff --git a/x-pack/plugins/event_log/README.md b/x-pack/plugins/event_log/README.md
index 2272341c65f5e..032f77543acb9 100644
--- a/x-pack/plugins/event_log/README.md
+++ b/x-pack/plugins/event_log/README.md
@@ -101,11 +101,20 @@ Below is a document in the expected structure, with descriptions of the fields:
     logger: "name of the logger",
   },
 
-  // Rule fields. All of them are supported.
+  // Rule fields.
   // https://www.elastic.co/guide/en/ecs/current/ecs-rule.html
   rule: {
+    // Fields currently are populated:
+    id: "a823fd56-5467-4727-acb1-66809737d943", // rule id
+    category: "test", // rule type id
+    license: "basic", // rule type minimumLicenseRequired
+    name: "rule-name", //
+    ruleset: "alerts", // rule type producer
+    // Fields currently are not populated:
     author: ["Elastic"],
-    id: "a823fd56-5467-4727-acb1-66809737d943",
+    description: "Some rule description",
+    version: '1',
+    uuid: "uuid"
     // etc
   },
 
diff --git a/x-pack/plugins/event_log/generated/mappings.json b/x-pack/plugins/event_log/generated/mappings.json
index da04db1086aa8..3eadcc21257b0 100644
--- a/x-pack/plugins/event_log/generated/mappings.json
+++ b/x-pack/plugins/event_log/generated/mappings.json
@@ -214,6 +214,10 @@
                 "version": {
                     "ignore_above": 1024,
                     "type": "keyword"
+                },
+                "namespace": {
+                    "ignore_above": 1024,
+                    "type": "keyword"
                 }
             }
         },
diff --git a/x-pack/plugins/event_log/generated/schemas.ts b/x-pack/plugins/event_log/generated/schemas.ts
index a13b304e8adab..2a066ca0bd15b 100644
--- a/x-pack/plugins/event_log/generated/schemas.ts
+++ b/x-pack/plugins/event_log/generated/schemas.ts
@@ -91,6 +91,7 @@ export const EventSchema = schema.maybe(
         ruleset: ecsString(),
         uuid: ecsString(),
         version: ecsString(),
+        namespace: ecsString(),
       })
     ),
     user: schema.maybe(
diff --git a/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.test.ts b/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.test.ts
index 31c47bf9dc69d..a5acd823c20fd 100644
--- a/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.test.ts
+++ b/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.test.ts
@@ -218,4 +218,81 @@ describe('Fleet - storedPackagePoliciesToAgentInputs', () => {
       },
     ]);
   });
+
+  it('returns agent inputs with deeply merged config values', () => {
+    expect(
+      storedPackagePoliciesToAgentInputs([
+        {
+          ...mockPackagePolicy,
+          inputs: [
+            {
+              ...mockInput,
+              compiled_input: {
+                agent_input_template_group1_vars: {
+                  inputVar: 'input-value',
+                },
+                agent_input_template_group2_vars: {
+                  inputVar3: {
+                    testFieldGroup: {
+                      subField1: 'subfield1',
+                    },
+                    testField: 'test',
+                  },
+                },
+              },
+              config: {
+                agent_input_template_group1_vars: {
+                  value: {
+                    inputVar2: {},
+                  },
+                },
+                agent_input_template_group2_vars: {
+                  value: {
+                    inputVar3: {
+                      testFieldGroup: {
+                        subField2: 'subfield2',
+                      },
+                    },
+                    inputVar4: '',
+                  },
+                },
+              },
+            },
+          ],
+        },
+      ])
+    ).toEqual([
+      {
+        id: 'some-uuid',
+        revision: 1,
+        name: 'mock-package-policy',
+        type: 'test-logs',
+        data_stream: { namespace: 'default' },
+        use_output: 'default',
+        agent_input_template_group1_vars: {
+          inputVar: 'input-value',
+          inputVar2: {},
+        },
+        agent_input_template_group2_vars: {
+          inputVar3: {
+            testField: 'test',
+            testFieldGroup: {
+              subField1: 'subfield1',
+              subField2: 'subfield2',
+            },
+          },
+          inputVar4: '',
+        },
+        streams: [
+          {
+            id: 'test-logs-foo',
+            data_stream: { dataset: 'foo', type: 'logs' },
+            fooKey: 'fooValue1',
+            fooKey2: ['fooValue2'],
+          },
+          { id: 'test-logs-bar', data_stream: { dataset: 'bar', type: 'logs' } },
+        ],
+      },
+    ]);
+  });
 });
diff --git a/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.ts b/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.ts
index 61d7764a832b1..f262521461b98 100644
--- a/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.ts
+++ b/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.ts
@@ -5,6 +5,8 @@
  * 2.0.
  */
 
+import { merge } from 'lodash';
+
 import type { PackagePolicy, FullAgentPolicyInput, FullAgentPolicyInputStream } from '../types';
 import { DEFAULT_OUTPUT } from '../constants';
 
@@ -31,10 +33,6 @@ export const storedPackagePoliciesToAgentInputs = (
           namespace: packagePolicy.namespace || 'default',
         },
         use_output: DEFAULT_OUTPUT.name,
-        ...Object.entries(input.config || {}).reduce((acc, [key, { value }]) => {
-          acc[key] = value;
-          return acc;
-        }, {} as { [k: string]: any }),
         ...(input.compiled_input || {}),
         ...(input.streams.length
           ? {
@@ -56,6 +54,15 @@ export const storedPackagePoliciesToAgentInputs = (
           : {}),
       };
 
+      // deeply merge the input.config values with the full policy input
+      merge(
+        fullInput,
+        Object.entries(input.config || {}).reduce(
+          (acc, [key, { value }]) => ({ ...acc, [key]: value }),
+          {}
+        )
+      );
+
       if (packagePolicy.package) {
         fullInput.meta = {
           package: {
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/actions_menu.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/actions_menu.tsx
index 798ed4f038156..ecc538bd95e2a 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/actions_menu.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/actions_menu.tsx
@@ -101,7 +101,7 @@ export const AgentPolicyActionMenu = memo<{
               ) : null}
               {isEnrollmentFlyoutOpen && (
                 <EuiPortal>
-                  <AgentEnrollmentFlyout agentPolicies={[agentPolicy]} onClose={onClose} />
+                  <AgentEnrollmentFlyout agentPolicy={agentPolicy} onClose={onClose} />
                 </EuiPortal>
               )}
               <ContextMenuActions
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/advanced_agent_authentication_settings.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/advanced_agent_authentication_settings.tsx
new file mode 100644
index 0000000000000..25602b7e108fd
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/advanced_agent_authentication_settings.tsx
@@ -0,0 +1,196 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type { FunctionComponent } from 'react';
+import React, { useEffect, useState } from 'react';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { EuiButtonEmpty, EuiButton, EuiCallOut, EuiSelect, EuiSpacer, EuiText } from '@elastic/eui';
+
+import { SO_SEARCH_LIMIT } from '../../applications/fleet/constants';
+import type { GetEnrollmentAPIKeysResponse } from '../../applications/fleet/types';
+import {
+  sendGetEnrollmentAPIKeys,
+  useStartServices,
+  sendCreateEnrollmentAPIKey,
+} from '../../applications/fleet/hooks';
+
+interface Props {
+  agentPolicyId?: string;
+  onKeyChange: (key?: string) => void;
+}
+
+export const AdvancedAgentAuthenticationSettings: FunctionComponent<Props> = ({
+  agentPolicyId,
+  onKeyChange,
+}) => {
+  const { notifications } = useStartServices();
+  const [enrollmentAPIKeys, setEnrollmentAPIKeys] = useState<GetEnrollmentAPIKeysResponse['list']>(
+    []
+  );
+  // TODO: Remove this piece of state since we don't need it here. The currently selected enrollment API key only
+  // needs to live on the form
+  const [selectedEnrollmentApiKey, setSelectedEnrollmentApiKey] = useState<undefined | string>();
+  const [isLoadingEnrollmentKey, setIsLoadingEnrollmentKey] = useState(false);
+  const [isAuthenticationSettingsOpen, setIsAuthenticationSettingsOpen] = useState<boolean>(false);
+
+  const onCreateEnrollmentTokenClick = async () => {
+    setIsLoadingEnrollmentKey(true);
+    if (agentPolicyId) {
+      try {
+        const res = await sendCreateEnrollmentAPIKey({ policy_id: agentPolicyId });
+        if (res.error) {
+          throw res.error;
+        }
+        setIsLoadingEnrollmentKey(false);
+        if (!res.data?.item) {
+          return;
+        }
+        setEnrollmentAPIKeys([res.data.item]);
+        setSelectedEnrollmentApiKey(res.data.item.id);
+        notifications.toasts.addSuccess(
+          i18n.translate('xpack.fleet.newEnrollmentKey.keyCreatedToasts', {
+            defaultMessage: 'Enrollment token created',
+          })
+        );
+      } catch (error) {
+        setIsLoadingEnrollmentKey(false);
+        notifications.toasts.addError(error, {
+          title: 'Error',
+        });
+      }
+    }
+  };
+
+  useEffect(
+    function triggerOnKeyChangeEffect() {
+      if (onKeyChange) {
+        onKeyChange(selectedEnrollmentApiKey);
+      }
+    },
+    [onKeyChange, selectedEnrollmentApiKey]
+  );
+
+  useEffect(
+    function useEnrollmentKeysForAgentPolicyEffect() {
+      if (!agentPolicyId) {
+        setIsAuthenticationSettingsOpen(true);
+        setEnrollmentAPIKeys([]);
+        return;
+      }
+
+      async function fetchEnrollmentAPIKeys() {
+        try {
+          const res = await sendGetEnrollmentAPIKeys({
+            page: 1,
+            perPage: SO_SEARCH_LIMIT,
+          });
+          if (res.error) {
+            throw res.error;
+          }
+
+          if (!res.data) {
+            throw new Error('No data while fetching enrollment API keys');
+          }
+
+          setEnrollmentAPIKeys(
+            res.data.list.filter((key) => key.policy_id === agentPolicyId && key.active === true)
+          );
+        } catch (error) {
+          notifications.toasts.addError(error, {
+            title: 'Error',
+          });
+        }
+      }
+      fetchEnrollmentAPIKeys();
+    },
+    [agentPolicyId, notifications.toasts]
+  );
+
+  useEffect(
+    function useDefaultEnrollmentKeyForAgentPolicyEffect() {
+      if (
+        !selectedEnrollmentApiKey &&
+        enrollmentAPIKeys.length > 0 &&
+        enrollmentAPIKeys[0].policy_id === agentPolicyId
+      ) {
+        const enrollmentAPIKeyId = enrollmentAPIKeys[0].id;
+        setSelectedEnrollmentApiKey(enrollmentAPIKeyId);
+      }
+    },
+    [enrollmentAPIKeys, selectedEnrollmentApiKey, agentPolicyId]
+  );
+  return (
+    <>
+      <EuiButtonEmpty
+        flush="left"
+        iconType={isAuthenticationSettingsOpen ? 'arrowDown' : 'arrowRight'}
+        onClick={() => setIsAuthenticationSettingsOpen(!isAuthenticationSettingsOpen)}
+      >
+        <FormattedMessage
+          id="xpack.fleet.enrollmentStepAgentPolicy.showAuthenticationSettingsButton"
+          defaultMessage="Authentication settings"
+        />
+      </EuiButtonEmpty>
+      {isAuthenticationSettingsOpen && (
+        <>
+          <EuiSpacer size="m" />
+          {enrollmentAPIKeys.length && selectedEnrollmentApiKey ? (
+            <EuiSelect
+              fullWidth
+              options={enrollmentAPIKeys.map((key) => ({
+                value: key.id,
+                text: key.name,
+              }))}
+              value={selectedEnrollmentApiKey || undefined}
+              prepend={
+                <EuiText>
+                  <FormattedMessage
+                    id="xpack.fleet.enrollmentStepAgentPolicy.enrollmentTokenSelectLabel"
+                    defaultMessage="Enrollment token"
+                  />
+                </EuiText>
+              }
+              onChange={(e) => {
+                setSelectedEnrollmentApiKey(e.target.value);
+              }}
+            />
+          ) : (
+            <EuiCallOut
+              color="warning"
+              title={i18n.translate(
+                'xpack.fleet.enrollmentStepAgentPolicy.noEnrollmentTokensForSelectedPolicyCallout',
+                {
+                  defaultMessage: 'There are no enrollment tokens for the selected agent policy',
+                }
+              )}
+            >
+              <div className="eui-textBreakWord">
+                <FormattedMessage
+                  id="xpack.fleet.agentEnrenrollmentStepAgentPolicyollment.noEnrollmentTokensForSelectedPolicyCalloutDescription"
+                  defaultMessage="You must create and enrollment token in order to enroll agents with this policy"
+                />
+              </div>
+              <EuiSpacer size="m" />
+              <EuiButton
+                iconType="plusInCircle"
+                isLoading={isLoadingEnrollmentKey}
+                fill
+                onClick={onCreateEnrollmentTokenClick}
+              >
+                <FormattedMessage
+                  id="xpack.fleet.enrollmentStepAgentPolicy.setUpAgentsLink"
+                  defaultMessage="Create enrollment token"
+                />
+              </EuiButton>
+            </EuiCallOut>
+          )}
+        </>
+      )}
+    </>
+  );
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.mocks.ts b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.mocks.ts
new file mode 100644
index 0000000000000..f1055e7e2583e
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.mocks.ts
@@ -0,0 +1,49 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+jest.mock('../../hooks/use_request', () => {
+  const module = jest.requireActual('../../hooks/use_request');
+  return {
+    ...module,
+    useGetSettings: jest.fn(),
+    sendGetFleetStatus: jest.fn(),
+  };
+});
+
+jest.mock(
+  '../../applications/fleet/sections/agents/agent_requirements_page/fleet_server_requirement_page',
+  () => {
+    const module = jest.requireActual(
+      '../../applications/fleet/sections/agents/agent_requirements_page/fleet_server_requirement_page'
+    );
+    return {
+      ...module,
+      FleetServerRequirementPage: jest.fn(),
+      useFleetServerInstructions: jest.fn(),
+    };
+  }
+);
+
+/**
+ * These steps functions use hooks inside useMemo which is not compatible with jest currently
+ */
+jest.mock('./steps', () => {
+  const module = jest.requireActual('./steps');
+  return {
+    ...module,
+    AgentPolicySelectionStep: jest.fn(),
+    AgentEnrollmentKeySelectionStep: jest.fn(),
+  };
+});
+
+jest.mock('@elastic/eui', () => {
+  const module = jest.requireActual('@elastic/eui');
+  return {
+    ...module,
+    EuiSteps: 'eui-steps',
+  };
+});
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx
new file mode 100644
index 0000000000000..db9245b11b0f9
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_enrollment_flyout.test.tsx
@@ -0,0 +1,164 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import './agent_enrollment_flyout.test.mocks';
+
+import React from 'react';
+import { registerTestBed } from '@kbn/test/jest';
+import { act } from '@testing-library/react';
+
+import { coreMock } from 'src/core/public/mocks';
+
+import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public';
+
+import type { AgentPolicy } from '../../../common';
+import { useGetSettings, sendGetFleetStatus } from '../../hooks/use_request';
+import { FleetStatusProvider, ConfigContext } from '../../hooks';
+
+import { useFleetServerInstructions } from '../../applications/fleet/sections/agents/agent_requirements_page';
+
+import { AgentEnrollmentKeySelectionStep, AgentPolicySelectionStep } from './steps';
+
+import type { Props } from '.';
+import { AgentEnrollmentFlyout } from '.';
+
+const TestComponent = (props: Props) => (
+  <KibanaContextProvider services={coreMock.createStart()}>
+    <ConfigContext.Provider value={{ agents: { enabled: true, elasticsearch: {} }, enabled: true }}>
+      <FleetStatusProvider>
+        <AgentEnrollmentFlyout {...props} />
+      </FleetStatusProvider>
+    </ConfigContext.Provider>
+  </KibanaContextProvider>
+);
+
+const setup = async (props?: Props) => {
+  const testBed = await registerTestBed(TestComponent)(props);
+  const { find, component } = testBed;
+
+  return {
+    ...testBed,
+    actions: {
+      goToStandaloneTab: () =>
+        act(() => {
+          find('agentEnrollmentFlyout.standaloneTab').simulate('click');
+          component.update();
+        }),
+    },
+  };
+};
+
+type SetupReturn = ReturnType<typeof setup>;
+type TestBed = SetupReturn extends Promise<infer U> ? U : SetupReturn;
+
+const testAgentPolicy: AgentPolicy = {
+  id: 'test',
+  is_managed: false,
+  namespace: 'test',
+  package_policies: [],
+  revision: 1,
+  status: 'active',
+  updated_at: 'test',
+  updated_by: 'test',
+  name: 'test',
+};
+
+describe('<AgentEnrollmentFlyout />', () => {
+  let testBed: TestBed;
+
+  beforeEach(async () => {
+    (useGetSettings as jest.Mock).mockReturnValue({
+      data: { item: { fleet_server_hosts: ['test'] } },
+    });
+
+    (sendGetFleetStatus as jest.Mock).mockResolvedValue({
+      data: { isReady: true },
+    });
+
+    (useFleetServerInstructions as jest.Mock).mockReturnValue({
+      serviceToken: 'test',
+      getServiceToken: jest.fn(),
+      isLoadingServiceToken: false,
+      installCommand: jest.fn(),
+      platform: 'test',
+      setPlatform: jest.fn(),
+    });
+
+    await act(async () => {
+      testBed = await setup({
+        agentPolicies: [],
+        onClose: jest.fn(),
+      });
+      testBed.component.update();
+    });
+  });
+
+  afterEach(() => {
+    jest.clearAllMocks();
+  });
+
+  describe('managed instructions', () => {
+    it('uses the agent policy selection step', async () => {
+      const { exists } = testBed;
+      expect(exists('agentEnrollmentFlyout')).toBe(true);
+      expect(AgentPolicySelectionStep).toHaveBeenCalled();
+      expect(AgentEnrollmentKeySelectionStep).not.toHaveBeenCalled();
+    });
+
+    describe('with a specific policy', () => {
+      beforeEach(async () => {
+        jest.clearAllMocks();
+        await act(async () => {
+          testBed = await setup({
+            agentPolicy: testAgentPolicy,
+            onClose: jest.fn(),
+          });
+          testBed.component.update();
+        });
+      });
+
+      it('uses the configure enrollment step, not the agent policy selection step', () => {
+        const { exists } = testBed;
+        expect(exists('agentEnrollmentFlyout')).toBe(true);
+        expect(AgentPolicySelectionStep).not.toHaveBeenCalled();
+        expect(AgentEnrollmentKeySelectionStep).toHaveBeenCalled();
+      });
+    });
+  });
+
+  describe('standalone instructions', () => {
+    it('uses the agent policy selection step', async () => {
+      const { exists, actions } = testBed;
+      actions.goToStandaloneTab();
+      expect(exists('agentEnrollmentFlyout')).toBe(true);
+      expect(AgentPolicySelectionStep).toHaveBeenCalled();
+      expect(AgentEnrollmentKeySelectionStep).not.toHaveBeenCalled();
+    });
+
+    describe('with a specific policy', () => {
+      beforeEach(async () => {
+        jest.clearAllMocks();
+        await act(async () => {
+          testBed = await setup({
+            agentPolicy: testAgentPolicy,
+            onClose: jest.fn(),
+          });
+          testBed.component.update();
+        });
+      });
+
+      it('does not use either of the agent policy selection or enrollment key steps', () => {
+        const { exists, actions } = testBed;
+        jest.clearAllMocks();
+        expect(exists('agentEnrollmentFlyout')).toBe(true);
+        actions.goToStandaloneTab();
+        expect(AgentPolicySelectionStep).not.toHaveBeenCalled();
+        expect(AgentEnrollmentKeySelectionStep).not.toHaveBeenCalled();
+      });
+    });
+  });
+});
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_selection.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_selection.tsx
index dc239213baf36..f92b2d4825935 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_selection.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/agent_policy_selection.tsx
@@ -8,17 +8,13 @@
 import React, { useState, useEffect } from 'react';
 import { i18n } from '@kbn/i18n';
 import { FormattedMessage } from '@kbn/i18n/react';
-import { EuiButtonEmpty, EuiButton, EuiCallOut, EuiSelect, EuiSpacer, EuiText } from '@elastic/eui';
+import { EuiSelect, EuiSpacer, EuiText } from '@elastic/eui';
 
-import { SO_SEARCH_LIMIT } from '../../constants';
-import type { AgentPolicy, GetEnrollmentAPIKeysResponse } from '../../types';
-import {
-  sendGetEnrollmentAPIKeys,
-  useStartServices,
-  sendCreateEnrollmentAPIKey,
-} from '../../hooks';
+import type { AgentPolicy } from '../../types';
 import { AgentPolicyPackageBadges } from '../agent_policy_package_badges';
 
+import { AdvancedAgentAuthenticationSettings } from './advanced_agent_authentication_settings';
+
 type Props = {
   agentPolicies?: AgentPolicy[];
   onAgentPolicyChange?: (key?: string) => void;
@@ -33,131 +29,48 @@ type Props = {
     }
 );
 
+const resolveAgentId = (
+  agentPolicies?: AgentPolicy[],
+  selectedAgentId?: string
+): undefined | string => {
+  if (agentPolicies && agentPolicies.length && !selectedAgentId) {
+    if (agentPolicies.length === 1) {
+      return agentPolicies[0].id;
+    }
+
+    const defaultAgentPolicy = agentPolicies.find((agentPolicy) => agentPolicy.is_default);
+    if (defaultAgentPolicy) {
+      return defaultAgentPolicy.id;
+    }
+  }
+
+  return selectedAgentId;
+};
+
 export const EnrollmentStepAgentPolicy: React.FC<Props> = (props) => {
-  const { notifications } = useStartServices();
   const { withKeySelection, agentPolicies, onAgentPolicyChange, excludeFleetServer } = props;
   const onKeyChange = props.withKeySelection && props.onKeyChange;
-
-  const [isAuthenticationSettingsOpen, setIsAuthenticationSettingsOpen] = useState(false);
-  const [enrollmentAPIKeys, setEnrollmentAPIKeys] = useState<GetEnrollmentAPIKeysResponse['list']>(
-    []
+  const [selectedAgentId, setSelectedAgentId] = useState<undefined | string>(
+    () => resolveAgentId(agentPolicies, undefined) // no agent id selected yet
   );
-  const [isLoadingEnrollmentKey, setIsLoadingEnrollmentKey] = useState(false);
-
-  const [selectedState, setSelectedState] = useState<{
-    agentPolicyId?: string;
-    enrollmentAPIKeyId?: string;
-  }>({});
 
   useEffect(
     function triggerOnAgentPolicyChangeEffect() {
       if (onAgentPolicyChange) {
-        onAgentPolicyChange(selectedState.agentPolicyId);
-      }
-    },
-    [selectedState.agentPolicyId, onAgentPolicyChange]
-  );
-
-  useEffect(
-    function triggerOnKeyChangeEffect() {
-      if (!withKeySelection || !onKeyChange) {
-        return;
-      }
-
-      if (onKeyChange) {
-        onKeyChange(selectedState.enrollmentAPIKeyId);
+        onAgentPolicyChange(selectedAgentId);
       }
     },
-    [withKeySelection, onKeyChange, selectedState.enrollmentAPIKeyId]
+    [selectedAgentId, onAgentPolicyChange]
   );
 
   useEffect(
     function useDefaultAgentPolicyEffect() {
-      if (agentPolicies && agentPolicies.length && !selectedState.agentPolicyId) {
-        if (agentPolicies.length === 1) {
-          setSelectedState({
-            ...selectedState,
-            agentPolicyId: agentPolicies[0].id,
-          });
-          return;
-        }
-
-        const defaultAgentPolicy = agentPolicies.find((agentPolicy) => agentPolicy.is_default);
-        if (defaultAgentPolicy) {
-          setSelectedState({
-            ...selectedState,
-            agentPolicyId: defaultAgentPolicy.id,
-          });
-        }
+      const resolvedId = resolveAgentId(agentPolicies, selectedAgentId);
+      if (resolvedId !== selectedAgentId) {
+        setSelectedAgentId(resolvedId);
       }
     },
-    [agentPolicies, selectedState]
-  );
-
-  useEffect(
-    function useEnrollmentKeysForAgentPolicyEffect() {
-      if (!withKeySelection) {
-        return;
-      }
-      if (!selectedState.agentPolicyId) {
-        setIsAuthenticationSettingsOpen(true);
-        setEnrollmentAPIKeys([]);
-        return;
-      }
-
-      async function fetchEnrollmentAPIKeys() {
-        try {
-          const res = await sendGetEnrollmentAPIKeys({
-            page: 1,
-            perPage: SO_SEARCH_LIMIT,
-          });
-          if (res.error) {
-            throw res.error;
-          }
-
-          if (!res.data) {
-            throw new Error('No data while fetching enrollment API keys');
-          }
-
-          setEnrollmentAPIKeys(
-            res.data.list.filter(
-              (key) => key.policy_id === selectedState.agentPolicyId && key.active === true
-            )
-          );
-        } catch (error) {
-          notifications.toasts.addError(error, {
-            title: 'Error',
-          });
-        }
-      }
-      fetchEnrollmentAPIKeys();
-    },
-    [withKeySelection, selectedState.agentPolicyId, notifications.toasts]
-  );
-
-  useEffect(
-    function useDefaultEnrollmentKeyForAgentPolicyEffect() {
-      if (!withKeySelection) {
-        return;
-      }
-      if (
-        !selectedState.enrollmentAPIKeyId &&
-        enrollmentAPIKeys.length > 0 &&
-        enrollmentAPIKeys[0].policy_id === selectedState.agentPolicyId
-      ) {
-        const enrollmentAPIKeyId = enrollmentAPIKeys[0].id;
-        setSelectedState({
-          agentPolicyId: selectedState.agentPolicyId,
-          enrollmentAPIKeyId,
-        });
-      }
-    },
-    [
-      withKeySelection,
-      enrollmentAPIKeys,
-      selectedState.enrollmentAPIKeyId,
-      selectedState.agentPolicyId,
-    ]
+    [agentPolicies, selectedAgentId]
   );
 
   return (
@@ -177,125 +90,26 @@ export const EnrollmentStepAgentPolicy: React.FC<Props> = (props) => {
           value: agentPolicy.id,
           text: agentPolicy.name,
         }))}
-        value={selectedState.agentPolicyId || undefined}
-        onChange={(e) =>
-          setSelectedState({
-            agentPolicyId: e.target.value,
-            enrollmentAPIKeyId: undefined,
-          })
-        }
+        value={selectedAgentId || undefined}
+        onChange={(e) => setSelectedAgentId(e.target.value)}
         aria-label={i18n.translate('xpack.fleet.enrollmentStepAgentPolicy.policySelectAriaLabel', {
           defaultMessage: 'Agent policy',
         })}
       />
       <EuiSpacer size="m" />
-      {selectedState.agentPolicyId && (
+      {selectedAgentId && (
         <AgentPolicyPackageBadges
-          agentPolicyId={selectedState.agentPolicyId}
+          agentPolicyId={selectedAgentId}
           excludeFleetServer={excludeFleetServer}
         />
       )}
       {withKeySelection && onKeyChange && (
         <>
-          <EuiSpacer size="m" />
-          <EuiButtonEmpty
-            flush="left"
-            iconType={isAuthenticationSettingsOpen ? 'arrowDown' : 'arrowRight'}
-            onClick={() => setIsAuthenticationSettingsOpen(!isAuthenticationSettingsOpen)}
-          >
-            <FormattedMessage
-              id="xpack.fleet.enrollmentStepAgentPolicy.showAuthenticationSettingsButton"
-              defaultMessage="Authentication settings"
-            />
-          </EuiButtonEmpty>
-          {isAuthenticationSettingsOpen && (
-            <>
-              <EuiSpacer size="m" />
-              {enrollmentAPIKeys.length && selectedState.enrollmentAPIKeyId ? (
-                <EuiSelect
-                  fullWidth
-                  options={enrollmentAPIKeys.map((key) => ({
-                    value: key.id,
-                    text: key.name,
-                  }))}
-                  value={selectedState.enrollmentAPIKeyId || undefined}
-                  prepend={
-                    <EuiText>
-                      <FormattedMessage
-                        id="xpack.fleet.enrollmentStepAgentPolicy.enrollmentTokenSelectLabel"
-                        defaultMessage="Enrollment token"
-                      />
-                    </EuiText>
-                  }
-                  onChange={(e) => {
-                    setSelectedState({
-                      ...selectedState,
-                      enrollmentAPIKeyId: e.target.value,
-                    });
-                  }}
-                />
-              ) : (
-                <EuiCallOut
-                  color="warning"
-                  title={i18n.translate(
-                    'xpack.fleet.enrollmentStepAgentPolicy.noEnrollmentTokensForSelectedPolicyCallout',
-                    {
-                      defaultMessage:
-                        'There are no enrollment tokens for the selected agent policy',
-                    }
-                  )}
-                >
-                  <div className="eui-textBreakWord">
-                    <FormattedMessage
-                      id="xpack.fleet.agentEnrenrollmentStepAgentPolicyollment.noEnrollmentTokensForSelectedPolicyCalloutDescription"
-                      defaultMessage="You must create and enrollment token in order to enroll agents with this policy"
-                    />
-                  </div>
-                  <EuiSpacer size="m" />
-                  <EuiButton
-                    iconType="plusInCircle"
-                    isLoading={isLoadingEnrollmentKey}
-                    fill
-                    onClick={() => {
-                      setIsLoadingEnrollmentKey(true);
-                      if (selectedState.agentPolicyId) {
-                        sendCreateEnrollmentAPIKey({ policy_id: selectedState.agentPolicyId })
-                          .then((res) => {
-                            if (res.error) {
-                              throw res.error;
-                            }
-                            setIsLoadingEnrollmentKey(false);
-                            if (res.data?.item) {
-                              setEnrollmentAPIKeys([res.data.item]);
-                              setSelectedState({
-                                ...selectedState,
-                                enrollmentAPIKeyId: res.data.item.id,
-                              });
-                              notifications.toasts.addSuccess(
-                                i18n.translate('xpack.fleet.newEnrollmentKey.keyCreatedToasts', {
-                                  defaultMessage: 'Enrollment token created',
-                                })
-                              );
-                            }
-                          })
-                          .catch((error) => {
-                            setIsLoadingEnrollmentKey(false);
-                            notifications.toasts.addError(error, {
-                              title: 'Error',
-                            });
-                          });
-                      }
-                    }}
-                  >
-                    <FormattedMessage
-                      id="xpack.fleet.enrollmentStepAgentPolicy.setUpAgentsLink"
-                      defaultMessage="Create enrollment token"
-                    />
-                  </EuiButton>
-                </EuiCallOut>
-              )}
-            </>
-          )}
+          <EuiSpacer />
+          <AdvancedAgentAuthenticationSettings
+            onKeyChange={onKeyChange}
+            agentPolicyId={selectedAgentId}
+          />
         </>
       )}
     </>
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx
index 84f881e8baa0c..b91af80691033 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/index.tsx
@@ -16,25 +16,21 @@ import {
   EuiFlexGroup,
   EuiFlexItem,
   EuiButtonEmpty,
-  EuiButton,
   EuiFlyoutFooter,
   EuiTab,
   EuiTabs,
-  EuiCallOut,
-  EuiLink,
 } from '@elastic/eui';
 import { FormattedMessage } from '@kbn/i18n/react';
-import { i18n } from '@kbn/i18n';
 
 import { useGetSettings, useUrlModal } from '../../hooks';
-import type { AgentPolicy } from '../../types';
 
 import { ManagedInstructions } from './managed_instructions';
 import { StandaloneInstructions } from './standalone_instructions';
+import { MissingFleetServerHostCallout } from './missing_fleet_server_host_callout';
+import type { BaseProps } from './types';
 
-interface Props {
+export interface Props extends BaseProps {
   onClose: () => void;
-  agentPolicies?: AgentPolicy[];
 }
 
 export * from './agent_policy_selection';
@@ -42,51 +38,9 @@ export * from './managed_instructions';
 export * from './standalone_instructions';
 export * from './steps';
 
-const MissingFleetServerHostCallout: React.FunctionComponent = () => {
-  const { setModal } = useUrlModal();
-  return (
-    <EuiCallOut
-      title={i18n.translate('xpack.fleet.agentEnrollment.missingFleetHostCalloutTitle', {
-        defaultMessage: 'Missing URL for Fleet Server host',
-      })}
-    >
-      <FormattedMessage
-        id="xpack.fleet.agentEnrollment.missingFleetHostCalloutText"
-        defaultMessage="A URL for your Fleet Server host is required to enroll agents with Fleet. You can add this information in Fleet Settings. For more information, see the {link}."
-        values={{
-          link: (
-            <EuiLink
-              href="https://www.elastic.co/guide/en/fleet/current/index.html"
-              target="_blank"
-              external
-            >
-              <FormattedMessage
-                id="xpack.fleet.agentEnrollment.missingFleetHostGuideLink"
-                defaultMessage="Fleet User Guide"
-              />
-            </EuiLink>
-          ),
-        }}
-      />
-      <EuiSpacer size="m" />
-      <EuiButton
-        fill
-        iconType="gear"
-        onClick={() => {
-          setModal('settings');
-        }}
-      >
-        <FormattedMessage
-          id="xpack.fleet.agentEnrollment.fleetSettingsLink"
-          defaultMessage="Fleet Settings"
-        />
-      </EuiButton>
-    </EuiCallOut>
-  );
-};
-
 export const AgentEnrollmentFlyout: React.FunctionComponent<Props> = ({
   onClose,
+  agentPolicy,
   agentPolicies,
 }) => {
   const [mode, setMode] = useState<'managed' | 'standalone'>('managed');
@@ -105,7 +59,7 @@ export const AgentEnrollmentFlyout: React.FunctionComponent<Props> = ({
   }, [modal, lastModal, settings]);
 
   return (
-    <EuiFlyout onClose={onClose} size="m">
+    <EuiFlyout data-test-subj="agentEnrollmentFlyout" onClose={onClose} size="m">
       <EuiFlyoutHeader hasBorder aria-labelledby="FleetAgentEnrollmentFlyoutTitle">
         <EuiTitle size="m">
           <h2 id="FleetAgentEnrollmentFlyoutTitle">
@@ -124,13 +78,21 @@ export const AgentEnrollmentFlyout: React.FunctionComponent<Props> = ({
         </EuiText>
         <EuiSpacer size="l" />
         <EuiTabs style={{ marginBottom: '-25px' }}>
-          <EuiTab isSelected={mode === 'managed'} onClick={() => setMode('managed')}>
+          <EuiTab
+            data-test-subj="managedTab"
+            isSelected={mode === 'managed'}
+            onClick={() => setMode('managed')}
+          >
             <FormattedMessage
               id="xpack.fleet.agentEnrollment.enrollFleetTabLabel"
               defaultMessage="Enroll in Fleet"
             />
           </EuiTab>
-          <EuiTab isSelected={mode === 'standalone'} onClick={() => setMode('standalone')}>
+          <EuiTab
+            data-test-subj="standaloneTab"
+            isSelected={mode === 'standalone'}
+            onClick={() => setMode('standalone')}
+          >
             <FormattedMessage
               id="xpack.fleet.agentEnrollment.enrollStandaloneTabLabel"
               defaultMessage="Run standalone"
@@ -147,29 +109,21 @@ export const AgentEnrollmentFlyout: React.FunctionComponent<Props> = ({
         }
       >
         {fleetServerHosts.length === 0 && mode === 'managed' ? null : mode === 'managed' ? (
-          <ManagedInstructions agentPolicies={agentPolicies} />
+          <ManagedInstructions agentPolicy={agentPolicy} agentPolicies={agentPolicies} />
         ) : (
-          <StandaloneInstructions agentPolicies={agentPolicies} />
+          <StandaloneInstructions agentPolicy={agentPolicy} agentPolicies={agentPolicies} />
         )}
       </EuiFlyoutBody>
       <EuiFlyoutFooter>
-        <EuiFlexGroup justifyContent="spaceBetween">
+        <EuiFlexGroup justifyContent="flexStart">
           <EuiFlexItem grow={false}>
-            <EuiButtonEmpty onClick={onClose} flush="left">
+            <EuiButtonEmpty onClick={onClose}>
               <FormattedMessage
-                id="xpack.fleet.agentEnrollment.cancelButtonLabel"
-                defaultMessage="Cancel"
+                id="xpack.fleet.agentEnrollment.closeFlyoutButtonLabel"
+                defaultMessage="Close"
               />
             </EuiButtonEmpty>
           </EuiFlexItem>
-          <EuiFlexItem grow={false}>
-            <EuiButton fill onClick={onClose}>
-              <FormattedMessage
-                id="xpack.fleet.agentEnrollment.continueButtonLabel"
-                defaultMessage="Continue"
-              />
-            </EuiButton>
-          </EuiFlexItem>
         </EuiFlexGroup>
       </EuiFlyoutFooter>
     </EuiFlyout>
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/managed_instructions.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/managed_instructions.tsx
index 5f2e0d6e4c414..2bb8586a11503 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/managed_instructions.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/managed_instructions.tsx
@@ -11,8 +11,6 @@ import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/st
 import { i18n } from '@kbn/i18n';
 import { FormattedMessage } from '@kbn/i18n/react';
 
-import type { AgentPolicy } from '../../types';
-import { NewEnrollmentTokenModal } from '../../components';
 import { useGetOneEnrollmentAPIKey, useGetSettings, useLink, useFleetStatus } from '../../hooks';
 
 import { ManualInstructions } from '../../components/enrollment_instructions';
@@ -23,11 +21,10 @@ import {
   useFleetServerInstructions,
 } from '../../applications/fleet/sections/agents/agent_requirements_page';
 
-import { DownloadStep, AgentPolicySelectionStep } from './steps';
+import { DownloadStep, AgentPolicySelectionStep, AgentEnrollmentKeySelectionStep } from './steps';
+import type { BaseProps } from './types';
 
-interface Props {
-  agentPolicies?: AgentPolicy[];
-}
+type Props = BaseProps;
 
 const DefaultMissingRequirements = () => {
   const { getHref } = useLink();
@@ -56,7 +53,7 @@ const FleetServerMissingRequirements = () => {
   return <FleetServerRequirementPage />;
 };
 
-export const ManagedInstructions = React.memo<Props>(({ agentPolicies }) => {
+export const ManagedInstructions = React.memo<Props>(({ agentPolicy, agentPolicies }) => {
   const fleetStatus = useFleetStatus();
 
   const [selectedAPIKeyId, setSelectedAPIKeyId] = useState<string | undefined>();
@@ -78,11 +75,13 @@ export const ManagedInstructions = React.memo<Props>(({ agentPolicies }) => {
     const fleetServerHosts = settings.data?.item?.fleet_server_hosts || [];
     const baseSteps: EuiContainedStepProps[] = [
       DownloadStep(),
-      AgentPolicySelectionStep({
-        agentPolicies,
-        setSelectedAPIKeyId,
-        setIsFleetServerPolicySelected,
-      }),
+      !agentPolicy
+        ? AgentPolicySelectionStep({
+            agentPolicies,
+            setSelectedAPIKeyId,
+            setIsFleetServerPolicySelected,
+          })
+        : AgentEnrollmentKeySelectionStep({ agentPolicy, setSelectedAPIKeyId }),
     ];
     if (isFleetServerPolicySelected) {
       baseSteps.push(
@@ -103,6 +102,7 @@ export const ManagedInstructions = React.memo<Props>(({ agentPolicies }) => {
     }
     return baseSteps;
   }, [
+    agentPolicy,
     agentPolicies,
     selectedAPIKeyId,
     apiKey.data,
@@ -111,11 +111,6 @@ export const ManagedInstructions = React.memo<Props>(({ agentPolicies }) => {
     fleetServerInstructions,
   ]);
 
-  const [isModalOpen, setModalOpen] = useState(false);
-  const closeModal = () => {
-    setModalOpen(false);
-  };
-
   return (
     <>
       {fleetStatus.isReady ? (
@@ -128,10 +123,6 @@ export const ManagedInstructions = React.memo<Props>(({ agentPolicies }) => {
           </EuiText>
           <EuiSpacer size="l" />
           <EuiSteps steps={steps} />
-
-          {isModalOpen && (
-            <NewEnrollmentTokenModal agentPolicies={agentPolicies} onClose={closeModal} />
-          )}
         </>
       ) : fleetStatus.missingRequirements?.length === 1 &&
         fleetStatus.missingRequirements[0] === 'fleet_server' ? (
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/missing_fleet_server_host_callout.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/missing_fleet_server_host_callout.tsx
new file mode 100644
index 0000000000000..636032552a1ae
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/missing_fleet_server_host_callout.tsx
@@ -0,0 +1,56 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { EuiCallOut, EuiLink, EuiButton, EuiSpacer } from '@elastic/eui';
+
+import { useUrlModal } from '../../hooks';
+
+export const MissingFleetServerHostCallout: React.FunctionComponent = () => {
+  const { setModal } = useUrlModal();
+  return (
+    <EuiCallOut
+      title={i18n.translate('xpack.fleet.agentEnrollment.missingFleetHostCalloutTitle', {
+        defaultMessage: 'Missing URL for Fleet Server host',
+      })}
+    >
+      <FormattedMessage
+        id="xpack.fleet.agentEnrollment.missingFleetHostCalloutText"
+        defaultMessage="A URL for your Fleet Server host is required to enroll agents with Fleet. You can add this information in Fleet Settings. For more information, see the {link}."
+        values={{
+          link: (
+            <EuiLink
+              href="https://www.elastic.co/guide/en/fleet/current/index.html"
+              target="_blank"
+              external
+            >
+              <FormattedMessage
+                id="xpack.fleet.agentEnrollment.missingFleetHostGuideLink"
+                defaultMessage="Fleet User Guide"
+              />
+            </EuiLink>
+          ),
+        }}
+      />
+      <EuiSpacer size="m" />
+      <EuiButton
+        fill
+        iconType="gear"
+        onClick={() => {
+          setModal('settings');
+        }}
+      >
+        <FormattedMessage
+          id="xpack.fleet.agentEnrollment.fleetSettingsLink"
+          defaultMessage="Fleet Settings"
+        />
+      </EuiButton>
+    </EuiCallOut>
+  );
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/standalone_instructions.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/standalone_instructions.tsx
index 0fd846b074f98..59898b9190c00 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/standalone_instructions.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/standalone_instructions.tsx
@@ -22,24 +22,22 @@ import type { EuiContainedStepProps } from '@elastic/eui/src/components/steps/st
 import { i18n } from '@kbn/i18n';
 import { FormattedMessage } from '@kbn/i18n/react';
 
-import type { AgentPolicy } from '../../types';
 import { useStartServices, useLink, sendGetOneAgentPolicyFull } from '../../hooks';
 import { fullAgentPolicyToYaml, agentPolicyRouteService } from '../../services';
 
 import { DownloadStep, AgentPolicySelectionStep } from './steps';
+import type { BaseProps } from './types';
 
-interface Props {
-  agentPolicies?: AgentPolicy[];
-}
+type Props = BaseProps;
 
 const RUN_INSTRUCTIONS = './elastic-agent install';
 
-export const StandaloneInstructions = React.memo<Props>(({ agentPolicies }) => {
+export const StandaloneInstructions = React.memo<Props>(({ agentPolicy, agentPolicies }) => {
   const { getHref } = useLink();
   const core = useStartServices();
   const { notifications } = core;
 
-  const [selectedPolicyId, setSelectedPolicyId] = useState<string | undefined>();
+  const [selectedPolicyId, setSelectedPolicyId] = useState<string | undefined>(agentPolicy?.id);
   const [fullAgentPolicy, setFullAgentPolicy] = useState<any | undefined>();
 
   const downloadLink = selectedPolicyId
@@ -74,9 +72,11 @@ export const StandaloneInstructions = React.memo<Props>(({ agentPolicies }) => {
   }, [selectedPolicyId, notifications.toasts]);
 
   const yaml = useMemo(() => fullAgentPolicyToYaml(fullAgentPolicy), [fullAgentPolicy]);
-  const steps: EuiContainedStepProps[] = [
+  const steps = [
     DownloadStep(),
-    AgentPolicySelectionStep({ agentPolicies, setSelectedPolicyId, excludeFleetServer: true }),
+    !agentPolicy
+      ? AgentPolicySelectionStep({ agentPolicies, setSelectedPolicyId, excludeFleetServer: true })
+      : undefined,
     {
       title: i18n.translate('xpack.fleet.agentEnrollment.stepConfigureAgentTitle', {
         defaultMessage: 'Configure the agent',
@@ -178,7 +178,7 @@ export const StandaloneInstructions = React.memo<Props>(({ agentPolicies }) => {
         </>
       ),
     },
-  ];
+  ].filter(Boolean) as EuiContainedStepProps[];
 
   return (
     <>
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx
index fc22cbdd047c3..ea4fa626afbb6 100644
--- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps.tsx
@@ -5,7 +5,7 @@
  * 2.0.
  */
 
-import React, { useCallback } from 'react';
+import React, { useCallback, useMemo } from 'react';
 import { EuiText, EuiButton, EuiSpacer } from '@elastic/eui';
 import { FormattedMessage } from '@kbn/i18n/react';
 import { i18n } from '@kbn/i18n';
@@ -15,6 +15,7 @@ import { sendGetOneAgentPolicy } from '../../hooks';
 import { FLEET_SERVER_PACKAGE } from '../../constants';
 
 import { EnrollmentStepAgentPolicy } from './agent_policy_selection';
+import { AdvancedAgentAuthenticationSettings } from './advanced_agent_authentication_settings';
 
 export const DownloadStep = () => {
   return {
@@ -59,12 +60,14 @@ export const AgentPolicySelectionStep = ({
   setIsFleetServerPolicySelected?: (selected: boolean) => void;
   excludeFleetServer?: boolean;
 }) => {
-  const regularAgentPolicies = Array.isArray(agentPolicies)
-    ? agentPolicies.filter(
-        (policy) =>
-          policy && !policy.is_managed && (!excludeFleetServer || !policy.is_default_fleet_server)
-      )
-    : [];
+  const regularAgentPolicies = useMemo(() => {
+    return Array.isArray(agentPolicies)
+      ? agentPolicies.filter(
+          (policy) =>
+            policy && !policy.is_managed && (!excludeFleetServer || !policy.is_default_fleet_server)
+        )
+      : [];
+  }, [agentPolicies, excludeFleetServer]);
 
   const onAgentPolicyChange = useCallback(
     async (policyId?: string) => {
@@ -103,3 +106,35 @@ export const AgentPolicySelectionStep = ({
     ),
   };
 };
+
+export const AgentEnrollmentKeySelectionStep = ({
+  agentPolicy,
+  setSelectedAPIKeyId,
+}: {
+  agentPolicy: AgentPolicy;
+  setSelectedAPIKeyId: (key?: string) => void;
+}) => {
+  return {
+    title: i18n.translate('xpack.fleet.agentEnrollment.stepConfigurePolicyAuthenticationTitle', {
+      defaultMessage: 'Configure agent authentication',
+    }),
+    children: (
+      <>
+        <EuiText>
+          <FormattedMessage
+            id="xpack.fleet.agentEnrollment.agentAuthenticationSettings"
+            defaultMessage="{agentPolicyName} has been selected. Configure agent authentication based on the available policy options."
+            values={{
+              agentPolicyName: <strong>{agentPolicy.name}</strong>,
+            }}
+          />
+        </EuiText>
+        <EuiSpacer size="l" />
+        <AdvancedAgentAuthenticationSettings
+          agentPolicyId={agentPolicy.id}
+          onKeyChange={setSelectedAPIKeyId}
+        />
+      </>
+    ),
+  };
+};
diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts
new file mode 100644
index 0000000000000..b9bcf8fb3e4b2
--- /dev/null
+++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/types.ts
@@ -0,0 +1,20 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type { AgentPolicy } from '../../types';
+
+export interface BaseProps {
+  /**
+   * The user selected policy to be used
+   */
+  agentPolicy?: AgentPolicy;
+
+  /**
+   * A selection of policies for the user to choose from, will be ignored if `agentPolicy` has been provided
+   */
+  agentPolicies?: AgentPolicy[];
+}
diff --git a/x-pack/plugins/fleet/server/collectors/fleet_server_collector.ts b/x-pack/plugins/fleet/server/collectors/fleet_server_collector.ts
index d861b211b8848..9616ba11545e0 100644
--- a/x-pack/plugins/fleet/server/collectors/fleet_server_collector.ts
+++ b/x-pack/plugins/fleet/server/collectors/fleet_server_collector.ts
@@ -4,6 +4,8 @@
  * 2.0; you may not use this file except in compliance with the Elastic License
  * 2.0.
  */
+
+import { isBoom } from '@hapi/boom';
 import type { SavedObjectsClient, ElasticsearchClient } from 'kibana/server';
 
 import { packagePolicyService, settingsService } from '../services';
@@ -38,11 +40,18 @@ export const getFleetServerUsage = async (
     return DEFAULT_USAGE;
   }
 
-  const numHostsUrls =
-    (await settingsService.getSettings(soClient)).fleet_server_hosts?.length ?? 0;
+  const numHostsUrls = await settingsService
+    .getSettings(soClient)
+    .then((settings) => settings.fleet_server_hosts?.length ?? 0)
+    .catch((err) => {
+      if (isBoom(error) && error.output.statusCode === 404) {
+        return 0;
+      }
 
-  // Find all policies with Fleet server than query agent status
+      throw err;
+    });
 
+  // Find all policies with Fleet server than query agent status
   let hasMore = true;
   const policyIds = new Set<string>();
   let page = 1;
diff --git a/x-pack/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx
index 61ed2934a4001..a439a3b5788fb 100644
--- a/x-pack/plugins/lens/public/app_plugin/app.tsx
+++ b/x-pack/plugins/lens/public/app_plugin/app.tsx
@@ -351,7 +351,7 @@ export function App({
 
   return (
     <>
-      <div className="lnsApp">
+      <div className="lnsApp" data-test-subj="lnsApp">
         <LensTopNavMenu
           initialInput={initialInput}
           redirectToOrigin={redirectToOrigin}
diff --git a/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx b/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx
index 245e964bbd2e6..ecaae04232f8a 100644
--- a/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx
+++ b/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx
@@ -7,7 +7,7 @@
 
 import { isEqual } from 'lodash';
 import { i18n } from '@kbn/i18n';
-import React from 'react';
+import React, { useCallback, useMemo } from 'react';
 import { TopNavMenuData } from '../../../../../src/plugins/navigation/public';
 import { LensAppServices, LensTopNavActions, LensTopNavMenuProps } from './types';
 import { downloadMultipleAs } from '../../../../../src/plugins/share/public';
@@ -164,79 +164,152 @@ export const LensTopNavMenu = ({
   const unsavedTitle = i18n.translate('xpack.lens.app.unsavedFilename', {
     defaultMessage: 'unsaved',
   });
-  const topNavConfig = getLensTopNavConfig({
-    showSaveAndReturn: Boolean(
-      isLinkedToOriginatingApp &&
-        // Temporarily required until the 'by value' paradigm is default.
-        (dashboardFeatureFlag.allowByValueEmbeddables || Boolean(initialInput))
-    ),
-    enableExportToCSV: Boolean(isSaveable && activeData && Object.keys(activeData).length),
-    isByValueMode: getIsByValueMode(),
-    allowByValue: dashboardFeatureFlag.allowByValueEmbeddables,
-    showCancel: Boolean(isLinkedToOriginatingApp),
-    savingToLibraryPermitted,
-    savingToDashboardPermitted,
-    actions: {
-      exportToCSV: () => {
-        if (!activeData) {
-          return;
-        }
-        const datatables = Object.values(activeData);
-        const content = datatables.reduce<Record<string, { content: string; type: string }>>(
-          (memo, datatable, i) => {
-            // skip empty datatables
-            if (datatable) {
-              const postFix = datatables.length > 1 ? `-${i + 1}` : '';
+  const topNavConfig = useMemo(
+    () =>
+      getLensTopNavConfig({
+        showSaveAndReturn: Boolean(
+          isLinkedToOriginatingApp &&
+            // Temporarily required until the 'by value' paradigm is default.
+            (dashboardFeatureFlag.allowByValueEmbeddables || Boolean(initialInput))
+        ),
+        enableExportToCSV: Boolean(isSaveable && activeData && Object.keys(activeData).length),
+        isByValueMode: getIsByValueMode(),
+        allowByValue: dashboardFeatureFlag.allowByValueEmbeddables,
+        showCancel: Boolean(isLinkedToOriginatingApp),
+        savingToLibraryPermitted,
+        savingToDashboardPermitted,
+        actions: {
+          exportToCSV: () => {
+            if (!activeData) {
+              return;
+            }
+            const datatables = Object.values(activeData);
+            const content = datatables.reduce<Record<string, { content: string; type: string }>>(
+              (memo, datatable, i) => {
+                // skip empty datatables
+                if (datatable) {
+                  const postFix = datatables.length > 1 ? `-${i + 1}` : '';
 
-              memo[`${lastKnownDoc?.title || unsavedTitle}${postFix}.csv`] = {
-                content: exporters.datatableToCSV(datatable, {
-                  csvSeparator: uiSettings.get('csv:separator', ','),
-                  quoteValues: uiSettings.get('csv:quoteValues', true),
-                  formatFactory: data.fieldFormats.deserialize,
-                }),
-                type: exporters.CSV_MIME_TYPE,
-              };
+                  memo[`${lastKnownDoc?.title || unsavedTitle}${postFix}.csv`] = {
+                    content: exporters.datatableToCSV(datatable, {
+                      csvSeparator: uiSettings.get('csv:separator', ','),
+                      quoteValues: uiSettings.get('csv:quoteValues', true),
+                      formatFactory: data.fieldFormats.deserialize,
+                    }),
+                    type: exporters.CSV_MIME_TYPE,
+                  };
+                }
+                return memo;
+              },
+              {}
+            );
+            if (content) {
+              downloadMultipleAs(content);
             }
-            return memo;
           },
-          {}
-        );
-        if (content) {
-          downloadMultipleAs(content);
-        }
-      },
-      saveAndReturn: () => {
-        if (savingToDashboardPermitted && lastKnownDoc) {
-          // disabling the validation on app leave because the document has been saved.
-          onAppLeave((actions) => {
-            return actions.default();
-          });
-          runSave(
-            {
-              newTitle: lastKnownDoc.title,
-              newCopyOnSave: false,
-              isTitleDuplicateConfirmed: false,
-              returnToOrigin: true,
-            },
-            {
-              saveToLibrary:
-                (initialInput && attributeService.inputIsRefType(initialInput)) ?? false,
+          saveAndReturn: () => {
+            if (savingToDashboardPermitted && lastKnownDoc) {
+              // disabling the validation on app leave because the document has been saved.
+              onAppLeave((actions) => {
+                return actions.default();
+              });
+              runSave(
+                {
+                  newTitle: lastKnownDoc.title,
+                  newCopyOnSave: false,
+                  isTitleDuplicateConfirmed: false,
+                  returnToOrigin: true,
+                },
+                {
+                  saveToLibrary:
+                    (initialInput && attributeService.inputIsRefType(initialInput)) ?? false,
+                }
+              );
             }
-          );
-        }
-      },
-      showSaveModal: () => {
-        if (savingToDashboardPermitted || savingToLibraryPermitted) {
-          setIsSaveModalVisible(true);
-        }
-      },
-      cancel: () => {
-        if (redirectToOrigin) {
-          redirectToOrigin();
+          },
+          showSaveModal: () => {
+            if (savingToDashboardPermitted || savingToLibraryPermitted) {
+              setIsSaveModalVisible(true);
+            }
+          },
+          cancel: () => {
+            if (redirectToOrigin) {
+              redirectToOrigin();
+            }
+          },
+        },
+      }),
+    [
+      activeData,
+      attributeService,
+      dashboardFeatureFlag.allowByValueEmbeddables,
+      data.fieldFormats.deserialize,
+      getIsByValueMode,
+      initialInput,
+      isLinkedToOriginatingApp,
+      isSaveable,
+      lastKnownDoc,
+      onAppLeave,
+      redirectToOrigin,
+      runSave,
+      savingToDashboardPermitted,
+      savingToLibraryPermitted,
+      setIsSaveModalVisible,
+      uiSettings,
+      unsavedTitle,
+    ]
+  );
+
+  const onQuerySubmitWrapped = useCallback(
+    (payload) => {
+      const { dateRange, query: newQuery } = payload;
+      const currentRange = data.query.timefilter.timefilter.getTime();
+      if (dateRange.from !== currentRange.from || dateRange.to !== currentRange.to) {
+        data.query.timefilter.timefilter.setTime(dateRange);
+        trackUiEvent('app_date_change');
+      } else {
+        // Query has changed, renew the session id.
+        // Time change will be picked up by the time subscription
+        dispatchSetState({ searchSessionId: data.search.session.start() });
+        trackUiEvent('app_query_change');
+      }
+      if (newQuery) {
+        if (!isEqual(newQuery, query)) {
+          dispatchSetState({ query: newQuery });
         }
-      },
+      }
     },
-  });
+    [data.query.timefilter.timefilter, data.search.session, dispatchSetState, query]
+  );
+
+  const onSavedWrapped = useCallback(
+    (newSavedQuery) => {
+      dispatchSetState({ savedQuery: newSavedQuery });
+    },
+    [dispatchSetState]
+  );
+
+  const onSavedQueryUpdatedWrapped = useCallback(
+    (newSavedQuery) => {
+      const savedQueryFilters = newSavedQuery.attributes.filters || [];
+      const globalFilters = data.query.filterManager.getGlobalFilters();
+      data.query.filterManager.setFilters([...globalFilters, ...savedQueryFilters]);
+      dispatchSetState({
+        query: newSavedQuery.attributes.query,
+        savedQuery: { ...newSavedQuery },
+      }); // Shallow query for reference issues
+    },
+    [data.query.filterManager, dispatchSetState]
+  );
+
+  const onClearSavedQueryWrapped = useCallback(() => {
+    data.query.filterManager.setFilters(data.query.filterManager.getGlobalFilters());
+    dispatchSetState({
+      filters: data.query.filterManager.getGlobalFilters(),
+      query: data.query.queryString.getDefaultQuery(),
+      savedQuery: undefined,
+    });
+  }, [data.query.filterManager, data.query.queryString, dispatchSetState]);
 
   return (
     <TopNavMenu
@@ -244,44 +317,10 @@ export const LensTopNavMenu = ({
       config={topNavConfig}
       showSaveQuery={Boolean(application.capabilities.visualize.saveQuery)}
       savedQuery={savedQuery}
-      onQuerySubmit={(payload) => {
-        const { dateRange, query: newQuery } = payload;
-        const currentRange = data.query.timefilter.timefilter.getTime();
-        if (dateRange.from !== currentRange.from || dateRange.to !== currentRange.to) {
-          data.query.timefilter.timefilter.setTime(dateRange);
-          trackUiEvent('app_date_change');
-        } else {
-          // Query has changed, renew the session id.
-          // Time change will be picked up by the time subscription
-          dispatchSetState({ searchSessionId: data.search.session.start() });
-          trackUiEvent('app_query_change');
-        }
-        if (newQuery) {
-          if (!isEqual(newQuery, query)) {
-            dispatchSetState({ query: newQuery });
-          }
-        }
-      }}
-      onSaved={(newSavedQuery) => {
-        dispatchSetState({ savedQuery: newSavedQuery });
-      }}
-      onSavedQueryUpdated={(newSavedQuery) => {
-        const savedQueryFilters = newSavedQuery.attributes.filters || [];
-        const globalFilters = data.query.filterManager.getGlobalFilters();
-        data.query.filterManager.setFilters([...globalFilters, ...savedQueryFilters]);
-        dispatchSetState({
-          query: newSavedQuery.attributes.query,
-          savedQuery: { ...newSavedQuery },
-        }); // Shallow query for reference issues
-      }}
-      onClearSavedQuery={() => {
-        data.query.filterManager.setFilters(data.query.filterManager.getGlobalFilters());
-        dispatchSetState({
-          filters: data.query.filterManager.getGlobalFilters(),
-          query: data.query.queryString.getDefaultQuery(),
-          savedQuery: undefined,
-        });
-      }}
+      onQuerySubmit={onQuerySubmitWrapped}
+      onSaved={onSavedWrapped}
+      onSavedQueryUpdated={onSavedQueryUpdatedWrapped}
+      onClearSavedQuery={onClearSavedQueryWrapped}
       indexPatterns={indexPatternsForTopNav}
       query={query}
       dateRangeFrom={from}
diff --git a/x-pack/plugins/lens/public/datatable_visualization/components/cell_value.test.tsx b/x-pack/plugins/lens/public/datatable_visualization/components/cell_value.test.tsx
index 67255dc8a953e..aa8c6ffb26d17 100644
--- a/x-pack/plugins/lens/public/datatable_visualization/components/cell_value.test.tsx
+++ b/x-pack/plugins/lens/public/datatable_visualization/components/cell_value.test.tsx
@@ -192,5 +192,16 @@ describe('datatable cell renderer', () => {
         style: expect.objectContaining({ color: 'blue' }),
       });
     });
+
+    it('should not color the cell when the value is an array', async () => {
+      const columnConfig = getColumnConfiguration();
+      columnConfig.columns[0].colorMode = 'cell';
+
+      const { setCellProps } = await renderCellComponent(columnConfig, {
+        table: { ...table, rows: [{ a: [10, 123] }] },
+      });
+
+      expect(setCellProps).not.toHaveBeenCalled();
+    });
   });
 });
diff --git a/x-pack/plugins/lens/public/datatable_visualization/components/cell_value.tsx b/x-pack/plugins/lens/public/datatable_visualization/components/cell_value.tsx
index a6c50f00cb77f..14b8c8a36b431 100644
--- a/x-pack/plugins/lens/public/datatable_visualization/components/cell_value.tsx
+++ b/x-pack/plugins/lens/public/datatable_visualization/components/cell_value.tsx
@@ -13,6 +13,7 @@ import type { DataContextType } from './types';
 import { ColumnConfig } from './table_basic';
 import { getContrastColor } from '../../shared_components/coloring/utils';
 import { getOriginalId } from '../transpose_helpers';
+import { getNumericValue } from './shared_utils';
 
 export const createGridCell = (
   formatters: Record<string, ReturnType<FormatFactory>>,
@@ -37,7 +38,11 @@ export const createGridCell = (
       if (minMaxByColumnId?.[originalId]) {
         if (colorMode !== 'none' && palette?.params && getColorForValue) {
           // workout the bucket the value belongs to
-          const color = getColorForValue(rowValue, palette.params, minMaxByColumnId[originalId]);
+          const color = getColorForValue(
+            getNumericValue(rowValue),
+            palette.params,
+            minMaxByColumnId[originalId]
+          );
           if (color) {
             const style = { [colorMode === 'cell' ? 'backgroundColor' : 'color']: color };
             if (colorMode === 'cell' && color) {
diff --git a/x-pack/plugins/lens/public/datatable_visualization/components/columns.tsx b/x-pack/plugins/lens/public/datatable_visualization/components/columns.tsx
index ba24da8309ed7..5c53d40f999b7 100644
--- a/x-pack/plugins/lens/public/datatable_visualization/components/columns.tsx
+++ b/x-pack/plugins/lens/public/datatable_visualization/components/columns.tsx
@@ -51,7 +51,7 @@ export const createGridColumns = (
     columnId,
   }: Pick<EuiDataGridColumnCellActionProps, 'rowIndex' | 'columnId'>) => {
     const rowValue = table.rows[rowIndex][columnId];
-    const column = columnsReverseLookup[columnId];
+    const column = columnsReverseLookup?.[columnId];
     const contentsIsDefined = rowValue != null;
 
     const cellContent = formatFactory(column?.meta?.params).convert(rowValue);
diff --git a/x-pack/plugins/lens/public/datatable_visualization/components/shared_utils.tsx b/x-pack/plugins/lens/public/datatable_visualization/components/shared_utils.tsx
index 92a949e65c67e..815da92d9fca9 100644
--- a/x-pack/plugins/lens/public/datatable_visualization/components/shared_utils.tsx
+++ b/x-pack/plugins/lens/public/datatable_visualization/components/shared_utils.tsx
@@ -8,6 +8,13 @@
 import { Datatable } from 'src/plugins/expressions';
 import { getOriginalId } from '../transpose_helpers';
 
+export function getNumericValue(rowValue: number | number[] | undefined) {
+  if (rowValue == null || Array.isArray(rowValue)) {
+    return;
+  }
+  return rowValue;
+}
+
 export const findMinMaxByColumnId = (columnIds: string[], table: Datatable | undefined) => {
   const minMax: Record<string, { min: number; max: number; fallback?: boolean }> = {};
 
@@ -17,12 +24,13 @@ export const findMinMaxByColumnId = (columnIds: string[], table: Datatable | und
       minMax[originalId] = minMax[originalId] || { max: -Infinity, min: Infinity };
       table.rows.forEach((row) => {
         const rowValue = row[columnId];
-        if (rowValue != null) {
-          if (minMax[originalId].min > rowValue) {
-            minMax[originalId].min = rowValue;
+        const numericValue = getNumericValue(rowValue);
+        if (numericValue != null) {
+          if (minMax[originalId].min > numericValue) {
+            minMax[originalId].min = numericValue;
           }
-          if (minMax[originalId].max < rowValue) {
-            minMax[originalId].max = rowValue;
+          if (minMax[originalId].max < numericValue) {
+            minMax[originalId].max = numericValue;
           }
         }
       });
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.test.tsx
index 3936fb9e1a1b1..1ec48f516bd32 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.test.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.test.tsx
@@ -76,6 +76,8 @@ describe('ConfigPanel', () => {
       framePublicAPI: frame,
       dispatch: jest.fn(),
       core: coreMock.createStart(),
+      isFullscreen: false,
+      toggleFullscreen: jest.fn(),
     };
   }
 
@@ -119,19 +121,23 @@ describe('ConfigPanel', () => {
     expect(component.find(LayerPanel).exists()).toBe(false);
   });
 
-  it('allow datasources and visualizations to use setters', () => {
+  it('allow datasources and visualizations to use setters', async () => {
     const props = getDefaultProps();
     const component = mountWithIntl(<LayerPanels {...props} />);
     const { updateDatasource, updateAll } = component.find(LayerPanel).props();
 
     const updater = () => 'updated';
     updateDatasource('ds1', updater);
+    // wait for one tick so async updater has a chance to trigger
+    await new Promise((r) => setTimeout(r, 0));
     expect(props.dispatch).toHaveBeenCalledTimes(1);
     expect(props.dispatch.mock.calls[0][0].updater(props.datasourceStates.ds1.state)).toEqual(
       'updated'
     );
 
     updateAll('ds1', updater, props.visualizationState);
+    // wait for one tick so async updater has a chance to trigger
+    await new Promise((r) => setTimeout(r, 0));
     expect(props.dispatch).toHaveBeenCalledTimes(2);
     expect(props.dispatch.mock.calls[0][0].updater(props.datasourceStates.ds1.state)).toEqual(
       'updated'
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx
index c1ab2b4586ab3..81c044af532fb 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx
@@ -71,32 +71,54 @@ export function LayerPanels(
     },
     [dispatch]
   );
+  const updateDatasourceAsync = useMemo(
+    () => (datasourceId: string, newState: unknown) => {
+      // React will synchronously update if this is triggered from a third party component,
+      // which we don't want. The timeout lets user interaction have priority, then React updates.
+      setTimeout(() => {
+        updateDatasource(datasourceId, newState);
+      }, 0);
+    },
+    [updateDatasource]
+  );
   const updateAll = useMemo(
     () => (datasourceId: string, newDatasourceState: unknown, newVisualizationState: unknown) => {
-      dispatch({
-        type: 'UPDATE_STATE',
-        subType: 'UPDATE_ALL_STATES',
-        updater: (prevState) => {
-          const updatedDatasourceState =
-            typeof newDatasourceState === 'function'
-              ? newDatasourceState(prevState.datasourceStates[datasourceId].state)
-              : newDatasourceState;
-          return {
-            ...prevState,
-            datasourceStates: {
-              ...prevState.datasourceStates,
-              [datasourceId]: {
-                state: updatedDatasourceState,
-                isLoading: false,
+      // React will synchronously update if this is triggered from a third party component,
+      // which we don't want. The timeout lets user interaction have priority, then React updates.
+      setTimeout(() => {
+        dispatch({
+          type: 'UPDATE_STATE',
+          subType: 'UPDATE_ALL_STATES',
+          updater: (prevState) => {
+            const updatedDatasourceState =
+              typeof newDatasourceState === 'function'
+                ? newDatasourceState(prevState.datasourceStates[datasourceId].state)
+                : newDatasourceState;
+            return {
+              ...prevState,
+              datasourceStates: {
+                ...prevState.datasourceStates,
+                [datasourceId]: {
+                  state: updatedDatasourceState,
+                  isLoading: false,
+                },
+              },
+              visualization: {
+                ...prevState.visualization,
+                state: newVisualizationState,
               },
-            },
-            visualization: {
-              ...prevState.visualization,
-              state: newVisualizationState,
-            },
-            stagedPreview: undefined,
-          };
-        },
+              stagedPreview: undefined,
+            };
+          },
+        });
+      }, 0);
+    },
+    [dispatch]
+  );
+  const toggleFullscreen = useMemo(
+    () => () => {
+      dispatch({
+        type: 'TOGGLE_FULLSCREEN',
       });
     },
     [dispatch]
@@ -118,6 +140,7 @@ export function LayerPanels(
             visualizationState={visualizationState}
             updateVisualization={setVisualizationState}
             updateDatasource={updateDatasource}
+            updateDatasourceAsync={updateDatasourceAsync}
             updateAll={updateAll}
             isOnlyLayer={layerIds.length === 1}
             onRemoveLayer={() => {
@@ -135,6 +158,7 @@ export function LayerPanels(
               });
               removeLayerRef(layerId);
             }}
+            toggleFullscreen={toggleFullscreen}
           />
         ) : null
       )}
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss
index 91cd706ea77d1..135286fc2172b 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss
@@ -8,21 +8,36 @@
   position: absolute;
   left: 0;
   animation: euiFlyout $euiAnimSpeedNormal $euiAnimSlightResistance;
+
   @include euiBreakpoint('l', 'xl') {
     top: 0 !important;
     height: 100% !important;
   }
+
   @include euiBreakpoint('xs', 's', 'm') {
     @include euiFlyout;
   }
+
+  .lnsFrameLayout__sidebar-isFullscreen & {
+    border-left: $euiBorderThin; // Force border regardless of theme in fullscreen
+    box-shadow: none;
+  }
 }
 
 .lnsDimensionContainer__footer {
   padding: $euiSizeS;
+
+  .lnsFrameLayout__sidebar-isFullscreen & {
+    display: none;
+  }
 }
 
 .lnsDimensionContainer__header {
   padding: $euiSizeS $euiSizeXS;
+
+  .lnsFrameLayout__sidebar-isFullscreen & {
+    display: none;
+  }
 }
 
 .lnsDimensionContainer__headerTitle {
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx
index b14d391c2c969..2f3eb5043d610 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx
@@ -29,26 +29,33 @@ export function DimensionContainer({
   groupLabel,
   handleClose,
   panel,
+  isFullscreen,
   panelRef,
 }: {
   isOpen: boolean;
-  handleClose: () => void;
-  panel: React.ReactElement;
+  handleClose: () => boolean;
+  panel: React.ReactElement | null;
   groupLabel: string;
+  isFullscreen: boolean;
   panelRef: (el: HTMLDivElement) => void;
 }) {
   const [focusTrapIsEnabled, setFocusTrapIsEnabled] = useState(false);
 
   const closeFlyout = useCallback(() => {
-    handleClose();
-    setFocusTrapIsEnabled(false);
+    const canClose = handleClose();
+    if (canClose) {
+      setFocusTrapIsEnabled(false);
+    }
+    return canClose;
   }, [handleClose]);
 
   const closeOnEscape = useCallback(
     (event: KeyboardEvent) => {
       if (event.key === keys.ESCAPE) {
-        event.preventDefault();
-        closeFlyout();
+        const canClose = closeFlyout();
+        if (canClose) {
+          event.preventDefault();
+        }
       }
     },
     [closeFlyout]
@@ -69,7 +76,15 @@ export function DimensionContainer({
     <div ref={panelRef}>
       <EuiFocusTrap disabled={!focusTrapIsEnabled} clickOutsideDisables={true}>
         <EuiWindowEvent event="keydown" handler={closeOnEscape} />
-        <EuiOutsideClickDetector onOutsideClick={closeFlyout} isDisabled={!isOpen}>
+        <EuiOutsideClickDetector
+          onOutsideClick={() => {
+            if (isFullscreen) {
+              return;
+            }
+            closeFlyout();
+          }}
+          isDisabled={!isOpen}
+        >
           <div
             role="dialog"
             aria-labelledby="lnsDimensionContainerTitle"
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx
index 7ee7a27a53c7d..dd1241af14f5a 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx
@@ -78,6 +78,7 @@ describe('LayerPanel', () => {
       visualizationState: 'state',
       updateVisualization: jest.fn(),
       updateDatasource: jest.fn(),
+      updateDatasourceAsync: jest.fn(),
       updateAll: jest.fn(),
       framePublicAPI: frame,
       isOnlyLayer: true,
@@ -86,6 +87,8 @@ describe('LayerPanel', () => {
       core: coreMock.createStart(),
       layerIndex: 0,
       registerNewLayerRef: jest.fn(),
+      isFullscreen: false,
+      toggleFullscreen: jest.fn(),
     };
   }
 
@@ -255,7 +258,7 @@ describe('LayerPanel', () => {
     it('should not update the visualization if the datasource is incomplete', () => {
       (generateId as jest.Mock).mockReturnValue(`newid`);
       const updateAll = jest.fn();
-      const updateDatasource = jest.fn();
+      const updateDatasourceAsync = jest.fn();
 
       mockVisualization.getConfiguration.mockReturnValue({
         groups: [
@@ -273,7 +276,7 @@ describe('LayerPanel', () => {
       const component = mountWithIntl(
         <LayerPanel
           {...getDefaultProps()}
-          updateDatasource={updateDatasource}
+          updateDatasourceAsync={updateDatasourceAsync}
           updateAll={updateAll}
         />
       );
@@ -292,15 +295,88 @@ describe('LayerPanel', () => {
           mockDatasource.renderDimensionEditor.mock.calls.length - 1
         ][1].setState;
 
+      act(() => {
+        stateFn(
+          {
+            indexPatternId: '1',
+            columns: {},
+            columnOrder: [],
+            incompleteColumns: { newId: { operationType: 'count' } },
+          },
+          { isDimensionComplete: false }
+        );
+      });
+      expect(updateAll).not.toHaveBeenCalled();
+      expect(updateDatasourceAsync).toHaveBeenCalled();
+
       act(() => {
         stateFn({
           indexPatternId: '1',
           columns: {},
           columnOrder: [],
-          incompleteColumns: { newId: { operationType: 'count' } },
         });
       });
-      expect(updateAll).not.toHaveBeenCalled();
+      expect(updateAll).toHaveBeenCalled();
+    });
+
+    it('should remove the dimension when the datasource marks it as removed', () => {
+      const updateAll = jest.fn();
+      const updateDatasource = jest.fn();
+
+      mockVisualization.getConfiguration.mockReturnValue({
+        groups: [
+          {
+            groupLabel: 'A',
+            groupId: 'a',
+            accessors: [{ columnId: 'y' }],
+            filterOperations: () => true,
+            supportsMoreColumns: true,
+            dataTestSubj: 'lnsGroup',
+          },
+        ],
+      });
+
+      const component = mountWithIntl(
+        <LayerPanel
+          {...getDefaultProps()}
+          datasourceStates={{
+            ds1: {
+              isLoading: false,
+              state: {
+                layers: [
+                  {
+                    indexPatternId: '1',
+                    columns: {
+                      y: {
+                        operationType: 'moving_average',
+                        references: ['ref'],
+                      },
+                    },
+                    columnOrder: ['y'],
+                    incompleteColumns: {},
+                  },
+                ],
+              },
+            },
+          }}
+          updateDatasource={updateDatasource}
+          updateAll={updateAll}
+        />
+      );
+
+      act(() => {
+        component.find('[data-test-subj="lnsLayerPanel-dimensionLink"]').first().simulate('click');
+      });
+      component.update();
+
+      expect(mockDatasource.renderDimensionEditor).toHaveBeenCalledWith(
+        expect.any(Element),
+        expect.objectContaining({ columnId: 'y' })
+      );
+      const stateFn =
+        mockDatasource.renderDimensionEditor.mock.calls[
+          mockDatasource.renderDimensionEditor.mock.calls.length - 1
+        ][1].setState;
 
       act(() => {
         stateFn(
@@ -308,11 +384,19 @@ describe('LayerPanel', () => {
             indexPatternId: '1',
             columns: {},
             columnOrder: [],
+            incompleteColumns: { y: { operationType: 'average' } },
           },
-          { shouldReplaceDimension: true }
+          {
+            isDimensionComplete: false,
+          }
         );
       });
       expect(updateAll).toHaveBeenCalled();
+      expect(mockVisualization.removeDimension).toHaveBeenCalledWith(
+        expect.objectContaining({
+          columnId: 'y',
+        })
+      );
     });
 
     it('should keep the DimensionContainer open when configuring a new dimension', () => {
@@ -331,6 +415,7 @@ describe('LayerPanel', () => {
             accessors: [],
             filterOperations: () => true,
             supportsMoreColumns: true,
+            enableDimensionEditor: true,
             dataTestSubj: 'lnsGroup',
           },
         ],
@@ -345,6 +430,7 @@ describe('LayerPanel', () => {
             accessors: [{ columnId: 'newid' }],
             filterOperations: () => true,
             supportsMoreColumns: false,
+            enableDimensionEditor: true,
             dataTestSubj: 'lnsGroup',
           },
         ],
@@ -357,6 +443,20 @@ describe('LayerPanel', () => {
       component.update();
 
       expect(component.find('EuiFlyoutHeader').exists()).toBe(true);
+
+      const lastArgs =
+        mockDatasource.renderDimensionEditor.mock.calls[
+          mockDatasource.renderDimensionEditor.mock.calls.length - 1
+        ][1];
+
+      // Simulate what is called by the dimension editor
+      act(() => {
+        lastArgs.setState(lastArgs.state, {
+          isDimensionComplete: true,
+        });
+      });
+
+      expect(mockVisualization.renderDimensionEditor).toHaveBeenCalled();
     });
 
     it('should close the DimensionContainer when the active visualization changes', () => {
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx
index a605a94a34646..3a299de0fca6a 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx
@@ -42,6 +42,7 @@ export function LayerPanel(
     isOnlyLayer: boolean;
     updateVisualization: StateSetter<unknown>;
     updateDatasource: (datasourceId: string, newState: unknown) => void;
+    updateDatasourceAsync: (datasourceId: string, newState: unknown) => void;
     updateAll: (
       datasourceId: string,
       newDatasourcestate: unknown,
@@ -49,6 +50,8 @@ export function LayerPanel(
     ) => void;
     onRemoveLayer: () => void;
     registerNewLayerRef: (layerId: string, instance: HTMLDivElement | null) => void;
+    toggleFullscreen: () => void;
+    isFullscreen: boolean;
   }
 ) {
   const [activeDimension, setActiveDimension] = useState<ActiveDimensionState>(
@@ -65,6 +68,8 @@ export function LayerPanel(
     activeVisualization,
     updateVisualization,
     updateDatasource,
+    toggleFullscreen,
+    isFullscreen,
   } = props;
   const datasourcePublicAPI = framePublicAPI.datasourceLayers[layerId];
 
@@ -197,9 +202,16 @@ export function LayerPanel(
     setNextFocusedButtonId,
   ]);
 
+  const isDimensionPanelOpen = Boolean(activeId);
+
   return (
     <>
-      <section tabIndex={-1} ref={registerLayerRef} className="lnsLayerPanel">
+      <section
+        tabIndex={-1}
+        ref={registerLayerRef}
+        className="lnsLayerPanel"
+        style={{ visibility: isDimensionPanelOpen ? 'hidden' : 'visible' }}
+      >
         <EuiPanel data-test-subj={`lns-layerPanel-${layerIndex}`} paddingSize="s">
           <EuiFlexGroup gutterSize="s" alignItems="flexStart" responsive={false}>
             <EuiFlexItem grow={false} className="lnsLayerPanel__settingsFlexItem">
@@ -407,9 +419,16 @@ export function LayerPanel(
 
       <DimensionContainer
         panelRef={(el) => (panelRef.current = el)}
-        isOpen={!!activeId}
+        isOpen={isDimensionPanelOpen}
+        isFullscreen={isFullscreen}
         groupLabel={activeGroup?.groupLabel || ''}
         handleClose={() => {
+          if (
+            layerDatasource.canCloseDimensionEditor &&
+            !layerDatasource.canCloseDimensionEditor(layerDatasourceState)
+          ) {
+            return false;
+          }
           if (layerDatasource.updateStateOnCloseDimension) {
             const newState = layerDatasource.updateStateOnCloseDimension({
               state: layerDatasourceState,
@@ -421,9 +440,13 @@ export function LayerPanel(
             }
           }
           setActiveDimension(initialActiveDimensionState);
+          if (isFullscreen) {
+            toggleFullscreen();
+          }
+          return true;
         }}
         panel={
-          <>
+          <div>
             {activeGroup && activeId && (
               <NativeRenderer
                 render={layerDatasource.renderDimensionEditor}
@@ -435,46 +458,51 @@ export function LayerPanel(
                   hideGrouping: activeGroup.hideGrouping,
                   filterOperations: activeGroup.filterOperations,
                   dimensionGroups: groups,
+                  toggleFullscreen,
+                  isFullscreen,
                   setState: (
                     newState: unknown,
-                    {
-                      shouldReplaceDimension,
-                      shouldRemoveDimension,
-                    }: {
-                      shouldReplaceDimension?: boolean;
-                      shouldRemoveDimension?: boolean;
-                    } = {}
+                    { isDimensionComplete = true }: { isDimensionComplete?: boolean } = {}
                   ) => {
-                    if (shouldReplaceDimension || shouldRemoveDimension) {
+                    if (allAccessors.includes(activeId)) {
+                      if (isDimensionComplete) {
+                        props.updateDatasourceAsync(datasourceId, newState);
+                      } else {
+                        // The datasource can indicate that the previously-valid column is no longer
+                        // complete, which clears the visualization. This keeps the flyout open and reuses
+                        // the previous columnId
+                        props.updateAll(
+                          datasourceId,
+                          newState,
+                          activeVisualization.removeDimension({
+                            layerId,
+                            columnId: activeId,
+                            prevState: props.visualizationState,
+                          })
+                        );
+                      }
+                    } else if (isDimensionComplete) {
                       props.updateAll(
                         datasourceId,
                         newState,
-                        shouldRemoveDimension
-                          ? activeVisualization.removeDimension({
-                              layerId,
-                              columnId: activeId,
-                              prevState: props.visualizationState,
-                            })
-                          : activeVisualization.setDimension({
-                              layerId,
-                              groupId: activeGroup.groupId,
-                              columnId: activeId,
-                              prevState: props.visualizationState,
-                            })
+                        activeVisualization.setDimension({
+                          layerId,
+                          groupId: activeGroup.groupId,
+                          columnId: activeId,
+                          prevState: props.visualizationState,
+                        })
                       );
+                      setActiveDimension({ ...activeDimension, isNew: false });
                     } else {
-                      props.updateDatasource(datasourceId, newState);
+                      props.updateDatasourceAsync(datasourceId, newState);
                     }
-                    setActiveDimension({
-                      ...activeDimension,
-                      isNew: false,
-                    });
                   },
                 }}
               />
             )}
             {activeGroup &&
               activeId &&
+              !isFullscreen &&
               !activeDimension.isNew &&
               activeVisualization.renderDimensionEditor &&
               activeGroup?.enableDimensionEditor && (
@@ -491,7 +519,7 @@ export function LayerPanel(
                   />
                 </div>
               )}
-          </>
+          </div>
         }
       />
     </>
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/types.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/types.ts
index 37b2198cfd51f..1af8c16fa1395 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/types.ts
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/types.ts
@@ -29,6 +29,7 @@ export interface ConfigPanelWrapperProps {
     }
   >;
   core: DatasourceDimensionEditorProps['core'];
+  isFullscreen: boolean;
 }
 
 export interface LayerPanelProps {
@@ -46,6 +47,7 @@ export interface LayerPanelProps {
     }
   >;
   core: DatasourceDimensionEditorProps['core'];
+  isFullscreen: boolean;
 }
 
 export interface LayerDatasourceDropProps {
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx
index 4710e03d336bc..161b0125a172a 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx
@@ -5,7 +5,7 @@
  * 2.0.
  */
 
-import React, { useEffect, useReducer, useState, useCallback } from 'react';
+import React, { useEffect, useReducer, useState, useCallback, useRef } from 'react';
 import { CoreStart } from 'kibana/public';
 import { isEqual } from 'lodash';
 import { PaletteRegistry } from 'src/plugins/charts/public';
@@ -30,6 +30,7 @@ import {
   applyVisualizeFieldSuggestions,
   getTopSuggestionForField,
   switchToSuggestion,
+  Suggestion,
 } from './suggestion_helpers';
 import { trackUiEvent } from '../../lens_ui_telemetry';
 import {
@@ -327,45 +328,37 @@ export function EditorFrame(props: EditorFrameProps) {
     ]
   );
 
-  const getSuggestionForField = React.useCallback(
-    (field: DragDropIdentifier) => {
-      const { activeDatasourceId, datasourceStates } = state;
-      const activeVisualizationId = state.visualization.activeId;
-      const visualizationState = state.visualization.state;
-      const { visualizationMap, datasourceMap } = props;
+  // Using a ref to prevent rerenders in the child components while keeping the latest state
+  const getSuggestionForField = useRef<(field: DragDropIdentifier) => Suggestion | undefined>();
+  getSuggestionForField.current = (field: DragDropIdentifier) => {
+    const { activeDatasourceId, datasourceStates } = state;
+    const activeVisualizationId = state.visualization.activeId;
+    const visualizationState = state.visualization.state;
+    const { visualizationMap, datasourceMap } = props;
 
-      if (!field || !activeDatasourceId) {
-        return;
-      }
+    if (!field || !activeDatasourceId) {
+      return;
+    }
 
-      return getTopSuggestionForField(
-        datasourceLayers,
-        activeVisualizationId,
-        visualizationMap,
-        visualizationState,
-        datasourceMap[activeDatasourceId],
-        datasourceStates,
-        field
-      );
-    },
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-    [
-      state.visualization.state,
-      props.datasourceMap,
-      props.visualizationMap,
-      state.activeDatasourceId,
-      state.datasourceStates,
-    ]
-  );
+    return getTopSuggestionForField(
+      datasourceLayers,
+      activeVisualizationId,
+      visualizationMap,
+      visualizationState,
+      datasourceMap[activeDatasourceId],
+      datasourceStates,
+      field
+    );
+  };
 
   const hasSuggestionForField = useCallback(
-    (field: DragDropIdentifier) => getSuggestionForField(field) !== undefined,
+    (field: DragDropIdentifier) => getSuggestionForField.current!(field) !== undefined,
     [getSuggestionForField]
   );
 
   const dropOntoWorkspace = useCallback(
     (field) => {
-      const suggestion = getSuggestionForField(field);
+      const suggestion = getSuggestionForField.current!(field);
       if (suggestion) {
         trackUiEvent('drop_onto_workspace');
         switchToSuggestion(dispatch, suggestion, 'SWITCH_VISUALIZATION');
@@ -377,6 +370,7 @@ export function EditorFrame(props: EditorFrameProps) {
   return (
     <RootDragDropProvider>
       <FrameLayout
+        isFullscreen={Boolean(state.isFullscreenDatasource)}
         dataPanel={
           <DataPanelWrapper
             datasourceMap={props.datasourceMap}
@@ -414,6 +408,7 @@ export function EditorFrame(props: EditorFrameProps) {
               visualizationState={state.visualization.state}
               framePublicAPI={framePublicAPI}
               core={props.core}
+              isFullscreen={Boolean(state.isFullscreenDatasource)}
             />
           )
         }
@@ -429,11 +424,12 @@ export function EditorFrame(props: EditorFrameProps) {
               visualizationState={state.visualization.state}
               visualizationMap={props.visualizationMap}
               dispatch={dispatch}
+              isFullscreen={Boolean(state.isFullscreenDatasource)}
               ExpressionRenderer={props.ExpressionRenderer}
               core={props.core}
               plugins={props.plugins}
               visualizeTriggerFieldContext={visualizeTriggerFieldContext}
-              getSuggestionForField={getSuggestionForField}
+              getSuggestionForField={getSuggestionForField.current}
             />
           )
         }
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.scss
index 0756c13f6999b..282e69cd7636c 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.scss
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.scss
@@ -67,9 +67,16 @@ a tilemap in an iframe: https://github.com/elastic/kibana/issues/16457 */
   padding: $euiSize $euiSize 0;
   position: relative;
   z-index: $lnsZLevel1;
+
   &:first-child {
     padding-left: $euiSize;
   }
+
+  &.lnsFrameLayout__pageBody-isFullscreen {
+    background: $euiColorEmptyShade;
+    flex: 1;
+    padding: 0;
+  }
 }
 
 .lnsFrameLayout__sidebar {
@@ -81,6 +88,13 @@ a tilemap in an iframe: https://github.com/elastic/kibana/issues/16457 */
   position: relative;
 }
 
+.lnsFrameLayout-isFullscreen .lnsFrameLayout__sidebar--left,
+.lnsFrameLayout-isFullscreen .lnsFrameLayout__suggestionPanel {
+  // Hide the datapanel and suggestions in fullscreen mode. Using display: none does trigger
+  // a rerender when the container becomes visible again, maybe pushing offscreen is better
+  display: none;
+}
+
 .lnsFrameLayout__sidebar--right {
   flex-basis: 25%;
   background-color: lightOrDarkTheme($euiColorLightestShade, $euiColorInk);
@@ -106,3 +120,8 @@ a tilemap in an iframe: https://github.com/elastic/kibana/issues/16457 */
     }
   }
 }
+
+.lnsFrameLayout__sidebar-isFullscreen {
+  flex: 1;
+  max-width: none;
+}
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx
index a54901a2a2fe1..f27e0f9c24d7b 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx
@@ -10,23 +10,32 @@ import './frame_layout.scss';
 import React from 'react';
 import { EuiPage, EuiPageBody, EuiScreenReaderOnly } from '@elastic/eui';
 import { i18n } from '@kbn/i18n';
+import classNames from 'classnames';
 
 export interface FrameLayoutProps {
   dataPanel: React.ReactNode;
   configPanel?: React.ReactNode;
   suggestionsPanel?: React.ReactNode;
   workspacePanel?: React.ReactNode;
+  isFullscreen?: boolean;
 }
 
 export function FrameLayout(props: FrameLayoutProps) {
   return (
-    <EuiPage className="lnsFrameLayout">
+    <EuiPage
+      className={classNames('lnsFrameLayout', {
+        'lnsFrameLayout-isFullscreen': props.isFullscreen,
+      })}
+    >
       <EuiPageBody
         restrictWidth={false}
         className="lnsFrameLayout__pageContent"
         aria-labelledby="lns_ChartTitle"
       >
-        <section className="lnsFrameLayout__sidebar" aria-labelledby="dataPanelId">
+        <section
+          className={classNames('lnsFrameLayout__sidebar lnsFrameLayout__sidebar--left', {})}
+          aria-labelledby="dataPanelId"
+        >
           <EuiScreenReaderOnly>
             <h2 id="dataPanelId">
               {i18n.translate('xpack.lens.section.dataPanelLabel', {
@@ -36,7 +45,13 @@ export function FrameLayout(props: FrameLayoutProps) {
           </EuiScreenReaderOnly>
           {props.dataPanel}
         </section>
-        <section className="lnsFrameLayout__pageBody" aria-labelledby="workspaceId">
+        <section
+          className={classNames('lnsFrameLayout__pageBody', {
+            // eslint-disable-next-line @typescript-eslint/naming-convention
+            'lnsFrameLayout__pageBody-isFullscreen': props.isFullscreen,
+          })}
+          aria-labelledby="workspaceId"
+        >
           <EuiScreenReaderOnly>
             <h2 id="workspaceId">
               {i18n.translate('xpack.lens.section.workspaceLabel', {
@@ -45,10 +60,13 @@ export function FrameLayout(props: FrameLayoutProps) {
             </h2>
           </EuiScreenReaderOnly>
           {props.workspacePanel}
-          {props.suggestionsPanel}
+          <div className="lnsFrameLayout__suggestionPanel">{props.suggestionsPanel}</div>
         </section>
         <section
-          className="lnsFrameLayout__sidebar lnsFrameLayout__sidebar--right"
+          className={classNames('lnsFrameLayout__sidebar lnsFrameLayout__sidebar--right', {
+            // eslint-disable-next-line @typescript-eslint/naming-convention
+            'lnsFrameLayout__sidebar-isFullscreen': props.isFullscreen,
+          })}
           aria-labelledby="configPanel"
         >
           <EuiScreenReaderOnly>
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts
index aa365d1e66d6c..a87aa7a2cb428 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts
@@ -22,6 +22,7 @@ export interface EditorFrameState extends PreviewState {
   description?: string;
   stagedPreview?: PreviewState;
   activeDatasourceId: string | null;
+  isFullscreenDatasource?: boolean;
 }
 
 export type Action =
@@ -90,6 +91,9 @@ export type Action =
   | {
       type: 'SWITCH_DATASOURCE';
       newDatasourceId: string;
+    }
+  | {
+      type: 'TOGGLE_FULLSCREEN';
     };
 
 export function getActiveDatasourceIdFromDoc(doc?: Document) {
@@ -281,6 +285,8 @@ export const reducer = (state: EditorFrameState, action: Action): EditorFrameSta
         },
         stagedPreview: action.clearStagedPreview ? undefined : state.stagedPreview,
       };
+    case 'TOGGLE_FULLSCREEN':
+      return { ...state, isFullscreenDatasource: !state.isFullscreenDatasource };
     default:
       return state;
   }
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx
index 0c2eb4f39d895..8107b6646500d 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx
@@ -200,15 +200,16 @@ export function SuggestionPanel({
             visualizationState: currentVisualizationState,
             activeData: frame.activeData,
           })
-            .filter((suggestion) => !suggestion.hide)
             .filter(
               ({
+                hide,
                 visualizationId,
                 visualizationState: suggestionVisualizationState,
                 datasourceState: suggestionDatasourceState,
                 datasourceId: suggetionDatasourceId,
               }) => {
                 return (
+                  !hide &&
                   validateDatasourceAndVisualization(
                     suggetionDatasourceId ? datasourceMap[suggetionDatasourceId] : null,
                     suggestionDatasourceState,
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx
index 1d248c4411023..38e9bb868b26a 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx
@@ -64,6 +64,8 @@ const defaultProps = {
     data: mockDataPlugin(),
   },
   getSuggestionForField: () => undefined,
+  isFullscreen: false,
+  toggleFullscreen: jest.fn(),
 };
 
 describe('workspace_panel', () => {
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx
index 45abbf120042d..01d4e84ec4374 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx
@@ -79,6 +79,7 @@ export interface WorkspacePanelProps {
   title?: string;
   visualizeTriggerFieldContext?: VisualizeFieldContext;
   getSuggestionForField: (field: DragDropIdentifier) => Suggestion | undefined;
+  isFullscreen: boolean;
 }
 
 interface WorkspaceState {
@@ -134,6 +135,7 @@ export const InnerWorkspacePanel = React.memo(function InnerWorkspacePanel({
   title,
   visualizeTriggerFieldContext,
   suggestionForDraggedField,
+  isFullscreen,
 }: Omit<WorkspacePanelProps, 'getSuggestionForField'> & {
   suggestionForDraggedField: Suggestion | undefined;
 }) {
@@ -346,6 +348,8 @@ export const InnerWorkspacePanel = React.memo(function InnerWorkspacePanel({
     );
   };
 
+  const element = expression !== null ? renderVisualization() : renderEmptyWorkspace();
+
   const dragDropContext = useContext(DragContext);
 
   const renderDragDrop = () => {
@@ -363,7 +367,10 @@ export const InnerWorkspacePanel = React.memo(function InnerWorkspacePanel({
       customWorkspaceRenderer()
     ) : (
       <DragDrop
-        className="lnsWorkspacePanel__dragDrop"
+        className={classNames('lnsWorkspacePanel__dragDrop', {
+          // eslint-disable-next-line @typescript-eslint/naming-convention
+          'lnsWorkspacePanel__dragDrop--fullscreen': isFullscreen,
+        })}
         dataTestSubj="lnsWorkspace"
         draggable={false}
         dropTypes={suggestionForDraggedField ? ['field_add'] : undefined}
@@ -372,8 +379,7 @@ export const InnerWorkspacePanel = React.memo(function InnerWorkspacePanel({
         order={dropProps.order}
       >
         <EuiPageContentBody className="lnsWorkspacePanelWrapper__pageContentBody">
-          {renderVisualization()}
-          {Boolean(suggestionForDraggedField) && expression !== null && renderEmptyWorkspace()}
+          {element}
         </EuiPageContentBody>
       </DragDrop>
     );
@@ -389,6 +395,7 @@ export const InnerWorkspacePanel = React.memo(function InnerWorkspacePanel({
       datasourceStates={datasourceStates}
       datasourceMap={datasourceMap}
       visualizationMap={visualizationMap}
+      isFullscreen={isFullscreen}
     >
       {renderDragDrop()}
     </WorkspacePanelWrapper>
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.scss
index e687e478cd368..21e3f9aa36674 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.scss
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.scss
@@ -31,6 +31,10 @@
       overflow: hidden;
     }
   }
+
+  &.lnsWorkspacePanelWrapper--fullscreen {
+    margin-bottom: 0;
+  }
 }
 
 .lnsWorkspacePanel__dragDrop {
@@ -62,6 +66,10 @@
       animation: lnsWorkspacePanel__illustrationPulseContinuous 1.5s ease-in-out 0s infinite normal forwards;
     }
   }
+
+  &.lnsWorkspacePanel__dragDrop--fullscreen {
+    border: none;
+  }
 }
 
 .lnsWorkspacePanel__emptyContent {
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.test.tsx
index 7bb467df9ab0e..c18b362e2faa4 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.test.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.test.tsx
@@ -37,6 +37,7 @@ describe('workspace_panel_wrapper', () => {
         visualizationMap={{ myVis: mockVisualization }}
         datasourceMap={{}}
         datasourceStates={{}}
+        isFullscreen={false}
       >
         <MyChild />
       </WorkspacePanelWrapper>
@@ -58,6 +59,7 @@ describe('workspace_panel_wrapper', () => {
         visualizationMap={{ myVis: { ...mockVisualization, renderToolbar: renderToolbarMock } }}
         datasourceMap={{}}
         datasourceStates={{}}
+        isFullscreen={false}
       />
     );
 
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx
index ec12e9e400203..6724002d23e0b 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx
@@ -10,6 +10,7 @@ import './workspace_panel_wrapper.scss';
 import React, { useCallback } from 'react';
 import { i18n } from '@kbn/i18n';
 import { EuiPageContent, EuiFlexGroup, EuiFlexItem, EuiScreenReaderOnly } from '@elastic/eui';
+import classNames from 'classnames';
 import { Datasource, FramePublicAPI, Visualization } from '../../../types';
 import { NativeRenderer } from '../../../native_renderer';
 import { Action } from '../state_management';
@@ -32,6 +33,7 @@ export interface WorkspacePanelWrapperProps {
       state: unknown;
     }
   >;
+  isFullscreen: boolean;
 }
 
 export function WorkspacePanelWrapper({
@@ -44,6 +46,7 @@ export function WorkspacePanelWrapper({
   visualizationMap,
   datasourceMap,
   datasourceStates,
+  isFullscreen,
 }: WorkspacePanelWrapperProps) {
   const activeVisualization = visualizationId ? visualizationMap[visualizationId] : null;
   const setVisualizationState = useCallback(
@@ -85,40 +88,42 @@ export function WorkspacePanelWrapper({
           wrap={true}
           justifyContent="spaceBetween"
         >
-          <EuiFlexItem grow={false}>
-            <EuiFlexGroup
-              gutterSize="m"
-              direction="row"
-              responsive={false}
-              wrap={true}
-              className="lnsWorkspacePanelWrapper__toolbar"
-            >
-              <EuiFlexItem grow={false}>
-                <ChartSwitch
-                  data-test-subj="lnsChartSwitcher"
-                  visualizationMap={visualizationMap}
-                  visualizationId={visualizationId}
-                  visualizationState={visualizationState}
-                  datasourceMap={datasourceMap}
-                  datasourceStates={datasourceStates}
-                  dispatch={dispatch}
-                  framePublicAPI={framePublicAPI}
-                />
-              </EuiFlexItem>
-              {activeVisualization && activeVisualization.renderToolbar && (
+          {!isFullscreen ? (
+            <EuiFlexItem grow={false}>
+              <EuiFlexGroup
+                gutterSize="m"
+                direction="row"
+                responsive={false}
+                wrap={true}
+                className="lnsWorkspacePanelWrapper__toolbar"
+              >
                 <EuiFlexItem grow={false}>
-                  <NativeRenderer
-                    render={activeVisualization.renderToolbar}
-                    nativeProps={{
-                      frame: framePublicAPI,
-                      state: visualizationState,
-                      setState: setVisualizationState,
-                    }}
+                  <ChartSwitch
+                    data-test-subj="lnsChartSwitcher"
+                    visualizationMap={visualizationMap}
+                    visualizationId={visualizationId}
+                    visualizationState={visualizationState}
+                    datasourceMap={datasourceMap}
+                    datasourceStates={datasourceStates}
+                    dispatch={dispatch}
+                    framePublicAPI={framePublicAPI}
                   />
                 </EuiFlexItem>
-              )}
-            </EuiFlexGroup>
-          </EuiFlexItem>
+                {activeVisualization && activeVisualization.renderToolbar && (
+                  <EuiFlexItem grow={false}>
+                    <NativeRenderer
+                      render={activeVisualization.renderToolbar}
+                      nativeProps={{
+                        frame: framePublicAPI,
+                        state: visualizationState,
+                        setState: setVisualizationState,
+                      }}
+                    />
+                  </EuiFlexItem>
+                )}
+              </EuiFlexGroup>
+            </EuiFlexItem>
+          ) : null}
           <EuiFlexItem grow={false}>
             {warningMessages && warningMessages.length ? (
               <WarningsPopover>{warningMessages}</WarningsPopover>
@@ -126,7 +131,11 @@ export function WorkspacePanelWrapper({
           </EuiFlexItem>
         </EuiFlexGroup>
       </div>
-      <EuiPageContent className="lnsWorkspacePanelWrapper">
+      <EuiPageContent
+        className={classNames('lnsWorkspacePanelWrapper', {
+          'lnsWorkspacePanelWrapper--fullscreen': isFullscreen,
+        })}
+      >
         <EuiScreenReaderOnly>
           <h1 id="lns_ChartTitle" data-test-subj="lns_ChartTitle">
             {title ||
diff --git a/x-pack/plugins/lens/public/editor_frame_service/mocks.tsx b/x-pack/plugins/lens/public/editor_frame_service/mocks.tsx
index 38669d72474df..1762e7ff20fab 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/mocks.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/mocks.tsx
@@ -57,6 +57,7 @@ export function createMockVisualization(): jest.Mocked<Visualization> {
     setDimension: jest.fn(),
     removeDimension: jest.fn(),
     getErrorMessages: jest.fn((_state) => undefined),
+    renderDimensionEditor: jest.fn(),
   };
 }
 
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.scss b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.scss
index bf833c4a36932..874291ae25e34 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.scss
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.scss
@@ -2,7 +2,27 @@
   height: 100%;
 }
 
-.lnsIndexPatternDimensionEditor__section {
+.lnsIndexPatternDimensionEditor__header {
+  position: sticky;
+  top: 0;
+  background: $euiColorEmptyShade;
+  // Raise it above the elements that are after it in DOM order
+  z-index: $euiZLevel1;
+}
+
+.lnsIndexPatternDimensionEditor-isFullscreen {
+  position: absolute;
+  left: 0;
+  right: 0;
+  top: 0;
+  bottom: 0;
+
+  .lnsIndexPatternDimensionEditor__section {
+    height: 100%;
+  }
+}
+
+.lnsIndexPatternDimensionEditor__section--padded {
   padding: $euiSizeS;
 }
 
@@ -10,6 +30,14 @@
   background-color: $euiColorLightestShade;
 }
 
+.lnsIndexPatternDimensionEditor__section--top {
+  border-bottom: $euiBorderThin;
+}
+
+.lnsIndexPatternDimensionEditor__section--bottom {
+  border-top: $euiBorderThin;
+}
+
 .lnsIndexPatternDimensionEditor__columns {
   column-count: 2;
   column-gap: $euiSizeXL;
@@ -29,3 +57,9 @@
   padding-top: 0;
   padding-bottom: 0;
 }
+
+.lnsIndexPatternDimensionEditor__warning {
+  @include kbnThemeStyle('v7') {
+    border: none;
+  }
+}
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx
index 2ae7b9403a46d..3dd2d4a4ba3f5 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx
@@ -6,7 +6,7 @@
  */
 
 import './dimension_editor.scss';
-import React, { useState, useMemo } from 'react';
+import React, { useState, useMemo, useCallback } from 'react';
 import { i18n } from '@kbn/i18n';
 import {
   EuiListGroup,
@@ -17,6 +17,9 @@ import {
   EuiFormLabel,
   EuiToolTip,
   EuiText,
+  EuiTabs,
+  EuiTab,
+  EuiCallOut,
 } from '@elastic/eui';
 import { IndexPatternDimensionEditorProps } from './dimension_panel';
 import { OperationSupportMatrix } from './operation_support';
@@ -91,6 +94,8 @@ export function DimensionEditor(props: DimensionEditorProps) {
     hideGrouping,
     dateRange,
     dimensionGroups,
+    toggleFullscreen,
+    isFullscreen,
   } = props;
   const services = {
     data: props.data,
@@ -101,30 +106,34 @@ export function DimensionEditor(props: DimensionEditorProps) {
   };
   const { fieldByOperation, operationWithoutField } = operationSupportMatrix;
 
+  const selectedOperationDefinition =
+    selectedColumn && operationDefinitionMap[selectedColumn.operationType];
+
   const setStateWrapper = (
     setter: IndexPatternLayer | ((prevLayer: IndexPatternLayer) => IndexPatternLayer)
   ) => {
+    const prevOperationType =
+      operationDefinitionMap[state.layers[layerId].columns[columnId]?.operationType]?.input;
+
     const hypotheticalLayer = typeof setter === 'function' ? setter(state.layers[layerId]) : setter;
     const hasIncompleteColumns = Boolean(hypotheticalLayer.incompleteColumns?.[columnId]);
-    const prevOperationType =
-      operationDefinitionMap[hypotheticalLayer.columns[columnId]?.operationType]?.input;
     setState(
       (prevState) => {
         const layer = typeof setter === 'function' ? setter(prevState.layers[layerId]) : setter;
         return mergeLayer({ state: prevState, layerId, newLayer: layer });
       },
       {
-        shouldReplaceDimension: Boolean(hypotheticalLayer.columns[columnId]),
-        // clear the dimension if there's an incomplete column pending && previous operation was a fullReference operation
-        shouldRemoveDimension: Boolean(
-          hasIncompleteColumns && prevOperationType === 'fullReference'
-        ),
+        isDimensionComplete:
+          prevOperationType === 'fullReference'
+            ? !hasIncompleteColumns
+            : Boolean(hypotheticalLayer.columns[columnId]),
       }
     );
   };
 
-  const selectedOperationDefinition =
-    selectedColumn && operationDefinitionMap[selectedColumn.operationType];
+  const setIsCloseable = (isCloseable: boolean) => {
+    setState((prevState) => ({ ...prevState, isDimensionClosePrevented: !isCloseable }));
+  };
 
   const incompleteInfo = (state.layers[layerId].incompleteColumns ?? {})[columnId];
   const incompleteOperation = incompleteInfo?.operationType;
@@ -132,14 +141,16 @@ export function DimensionEditor(props: DimensionEditorProps) {
 
   const ParamEditor = selectedOperationDefinition?.paramEditor;
 
+  const [temporaryQuickFunction, setQuickFunction] = useState(false);
+
   const possibleOperations = useMemo(() => {
     return Object.values(operationDefinitionMap)
       .filter(({ hidden }) => !hidden)
+      .filter(({ type }) => fieldByOperation[type]?.size || operationWithoutField.has(type))
       .sort((op1, op2) => {
         return op1.displayName.localeCompare(op2.displayName);
       })
-      .map((def) => def.type)
-      .filter((type) => fieldByOperation[type]?.size || operationWithoutField.has(type));
+      .map((def) => def.type);
   }, [fieldByOperation, operationWithoutField]);
 
   const [filterByOpenInitially, setFilterByOpenInitally] = useState(false);
@@ -245,37 +256,44 @@ export function DimensionEditor(props: DimensionEditorProps) {
               visualizationGroups: dimensionGroups,
               targetGroup: props.groupId,
             });
+            if (temporaryQuickFunction && newLayer.columns[columnId].operationType !== 'formula') {
+              // Only switch the tab once the formula is fully removed
+              setQuickFunction(false);
+            }
             setStateWrapper(newLayer);
             trackUiEvent(`indexpattern_dimension_operation_${operationType}`);
             return;
           } else if (!selectedColumn || !compatibleWithCurrentField) {
             const possibleFields = fieldByOperation[operationType] || new Set();
 
+            let newLayer: IndexPatternLayer;
             if (possibleFields.size === 1) {
-              setStateWrapper(
-                insertOrReplaceColumn({
-                  layer: props.state.layers[props.layerId],
-                  indexPattern: currentIndexPattern,
-                  columnId,
-                  op: operationType,
-                  field: currentIndexPattern.getFieldByName(possibleFields.values().next().value),
-                  visualizationGroups: dimensionGroups,
-                  targetGroup: props.groupId,
-                })
-              );
+              newLayer = insertOrReplaceColumn({
+                layer: props.state.layers[props.layerId],
+                indexPattern: currentIndexPattern,
+                columnId,
+                op: operationType,
+                field: currentIndexPattern.getFieldByName(possibleFields.values().next().value),
+                visualizationGroups: dimensionGroups,
+                targetGroup: props.groupId,
+              });
             } else {
-              setStateWrapper(
-                insertOrReplaceColumn({
-                  layer: props.state.layers[props.layerId],
-                  indexPattern: currentIndexPattern,
-                  columnId,
-                  op: operationType,
-                  field: undefined,
-                  visualizationGroups: dimensionGroups,
-                  targetGroup: props.groupId,
-                })
-              );
+              newLayer = insertOrReplaceColumn({
+                layer: props.state.layers[props.layerId],
+                indexPattern: currentIndexPattern,
+                columnId,
+                op: operationType,
+                field: undefined,
+                visualizationGroups: dimensionGroups,
+                targetGroup: props.groupId,
+              });
+              // );
+            }
+            if (temporaryQuickFunction && newLayer.columns[columnId].operationType !== 'formula') {
+              // Only switch the tab once the formula is fully removed
+              setQuickFunction(false);
             }
+            setStateWrapper(newLayer);
             trackUiEvent(`indexpattern_dimension_operation_${operationType}`);
             return;
           }
@@ -287,6 +305,9 @@ export function DimensionEditor(props: DimensionEditorProps) {
             return;
           }
 
+          if (temporaryQuickFunction) {
+            setQuickFunction(false);
+          }
           const newLayer = replaceColumn({
             layer: props.state.layers[props.layerId],
             indexPattern: currentIndexPattern,
@@ -315,9 +336,34 @@ export function DimensionEditor(props: DimensionEditorProps) {
       currentFieldIsInvalid
     );
 
-  return (
-    <div id={columnId}>
-      <div className="lnsIndexPatternDimensionEditor__section lnsIndexPatternDimensionEditor__section--shaded">
+  const shouldDisplayExtraOptions =
+    !currentFieldIsInvalid &&
+    !incompleteInfo &&
+    selectedColumn &&
+    selectedColumn.operationType !== 'formula';
+
+  const quickFunctions = (
+    <>
+      {temporaryQuickFunction && selectedColumn?.operationType === 'formula' && (
+        <>
+          <EuiCallOut
+            className="lnsIndexPatternDimensionEditor__warning"
+            size="s"
+            title={i18n.translate('xpack.lens.indexPattern.formulaWarning', {
+              defaultMessage: 'Formula currently applied',
+            })}
+            iconType="alert"
+            color="warning"
+          >
+            <p>
+              {i18n.translate('xpack.lens.indexPattern.formulaWarningText', {
+                defaultMessage: 'To overwrite your formula, select a quick function',
+              })}
+            </p>
+          </EuiCallOut>
+        </>
+      )}
+      <div className="lnsIndexPatternDimensionEditor__section lnsIndexPatternDimensionEditor__section--padded lnsIndexPatternDimensionEditor__section--shaded">
         <EuiFormLabel>
           {i18n.translate('xpack.lens.indexPattern.functionsLabel', {
             defaultMessage: 'Select a function',
@@ -336,7 +382,7 @@ export function DimensionEditor(props: DimensionEditorProps) {
         />
       </div>
       <EuiSpacer size="s" />
-      <div className="lnsIndexPatternDimensionEditor__section lnsIndexPatternDimensionEditor__section--shaded">
+      <div className="lnsIndexPatternDimensionEditor__section lnsIndexPatternDimensionEditor__section--padded lnsIndexPatternDimensionEditor__section--shaded">
         {!incompleteInfo &&
         selectedColumn &&
         'references' in selectedColumn &&
@@ -375,6 +421,9 @@ export function DimensionEditor(props: DimensionEditorProps) {
                     currentColumn: state.layers[layerId].columns[columnId],
                   })}
                   dimensionGroups={dimensionGroups}
+                  isFullscreen={isFullscreen}
+                  toggleFullscreen={toggleFullscreen}
+                  setIsCloseable={setIsCloseable}
                   {...services}
                 />
               );
@@ -385,7 +434,8 @@ export function DimensionEditor(props: DimensionEditorProps) {
 
         {!selectedColumn ||
         selectedOperationDefinition?.input === 'field' ||
-        (incompleteOperation && operationDefinitionMap[incompleteOperation].input === 'field') ? (
+        (incompleteOperation && operationDefinitionMap[incompleteOperation].input === 'field') ||
+        temporaryQuickFunction ? (
           <EuiFormRow
             data-test-subj="indexPattern-field-selection-row"
             label={i18n.translate('xpack.lens.indexPattern.chooseField', {
@@ -436,19 +486,20 @@ export function DimensionEditor(props: DimensionEditorProps) {
           </EuiFormRow>
         ) : null}
 
-        {!currentFieldIsInvalid && !incompleteInfo && selectedColumn && ParamEditor && (
-          <>
-            <ParamEditor
-              layer={state.layers[layerId]}
-              updateLayer={setStateWrapper}
-              columnId={columnId}
-              currentColumn={state.layers[layerId].columns[columnId]}
-              dateRange={dateRange}
-              indexPattern={currentIndexPattern}
-              operationDefinitionMap={operationDefinitionMap}
-              {...services}
-            />
-          </>
+        {shouldDisplayExtraOptions && ParamEditor && (
+          <ParamEditor
+            layer={state.layers[layerId]}
+            updateLayer={setStateWrapper}
+            columnId={columnId}
+            currentColumn={state.layers[layerId].columns[columnId]}
+            dateRange={dateRange}
+            indexPattern={currentIndexPattern}
+            operationDefinitionMap={operationDefinitionMap}
+            toggleFullscreen={toggleFullscreen}
+            isFullscreen={isFullscreen}
+            setIsCloseable={setIsCloseable}
+            {...services}
+          />
         )}
 
         {!currentFieldIsInvalid && !incompleteInfo && selectedColumn && (
@@ -546,9 +597,96 @@ export function DimensionEditor(props: DimensionEditorProps) {
       </div>
 
       <EuiSpacer size="s" />
+    </>
+  );
 
-      {!currentFieldIsInvalid && (
-        <div className="lnsIndexPatternDimensionEditor__section">
+  const formulaTab = ParamEditor ? (
+    <ParamEditor
+      layer={state.layers[layerId]}
+      updateLayer={setStateWrapper}
+      columnId={columnId}
+      currentColumn={state.layers[layerId].columns[columnId]}
+      dateRange={dateRange}
+      indexPattern={currentIndexPattern}
+      operationDefinitionMap={operationDefinitionMap}
+      toggleFullscreen={toggleFullscreen}
+      isFullscreen={isFullscreen}
+      setIsCloseable={setIsCloseable}
+      {...services}
+    />
+  ) : null;
+
+  const onFormatChange = useCallback(
+    (newFormat) => {
+      setState(
+        mergeLayer({
+          state,
+          layerId,
+          newLayer: updateColumnParam({
+            layer: state.layers[layerId],
+            columnId,
+            paramName: 'format',
+            value: newFormat,
+          }),
+        })
+      );
+    },
+    [columnId, layerId, setState, state]
+  );
+
+  return (
+    <div id={columnId}>
+      {!isFullscreen && operationSupportMatrix.operationWithoutField.has('formula') ? (
+        <EuiTabs size="s" className="lnsIndexPatternDimensionEditor__header">
+          <EuiTab
+            isSelected={temporaryQuickFunction || selectedColumn?.operationType !== 'formula'}
+            data-test-subj="lens-dimensionTabs-quickFunctions"
+            onClick={() => {
+              if (selectedColumn?.operationType === 'formula') {
+                setQuickFunction(true);
+              }
+            }}
+          >
+            {i18n.translate('xpack.lens.indexPattern.quickFunctionsLabel', {
+              defaultMessage: 'Quick functions',
+            })}
+          </EuiTab>
+          <EuiTab
+            isSelected={!temporaryQuickFunction && selectedColumn?.operationType === 'formula'}
+            data-test-subj="lens-dimensionTabs-formula"
+            onClick={() => {
+              if (selectedColumn?.operationType !== 'formula') {
+                setQuickFunction(false);
+                const newLayer = insertOrReplaceColumn({
+                  layer: props.state.layers[props.layerId],
+                  indexPattern: currentIndexPattern,
+                  columnId,
+                  op: 'formula',
+                  visualizationGroups: dimensionGroups,
+                });
+                setStateWrapper(newLayer);
+                trackUiEvent(`indexpattern_dimension_operation_formula`);
+                return;
+              } else {
+                setQuickFunction(false);
+              }
+            }}
+          >
+            {i18n.translate('xpack.lens.indexPattern.formulaLabel', {
+              defaultMessage: 'Formula',
+            })}
+          </EuiTab>
+        </EuiTabs>
+      ) : null}
+
+      {isFullscreen
+        ? formulaTab
+        : selectedOperationDefinition?.type === 'formula' && !temporaryQuickFunction
+        ? formulaTab
+        : quickFunctions}
+
+      {!isFullscreen && !currentFieldIsInvalid && !temporaryQuickFunction && (
+        <div className="lnsIndexPatternDimensionEditor__section lnsIndexPatternDimensionEditor__section--padded">
           {!incompleteInfo && selectedColumn && (
             <LabelInput
               value={selectedColumn.label}
@@ -578,7 +716,7 @@ export function DimensionEditor(props: DimensionEditorProps) {
             />
           )}
 
-          {!incompleteInfo && !hideGrouping && (
+          {!isFullscreen && !incompleteInfo && !hideGrouping && (
             <BucketNestingEditor
               layer={state.layers[props.layerId]}
               columnId={props.columnId}
@@ -589,31 +727,17 @@ export function DimensionEditor(props: DimensionEditorProps) {
             />
           )}
 
-          {selectedColumn &&
+          {!isFullscreen &&
+          selectedColumn &&
           (selectedColumn.dataType === 'number' || selectedColumn.operationType === 'range') ? (
-            <FormatSelector
-              selectedColumn={selectedColumn}
-              onChange={(newFormat) => {
-                setState(
-                  mergeLayer({
-                    state,
-                    layerId,
-                    newLayer: updateColumnParam({
-                      layer: state.layers[layerId],
-                      columnId,
-                      paramName: 'format',
-                      value: newFormat,
-                    }),
-                  })
-                );
-              }}
-            />
+            <FormatSelector selectedColumn={selectedColumn} onChange={onFormatChange} />
           ) : null}
         </div>
       )}
     </div>
   );
 }
+
 function getErrorMessage(
   selectedColumn: IndexPatternColumn | undefined,
   incompleteOperation: boolean,
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx
index 03db6141b917f..7e45b29521563 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx
@@ -208,6 +208,8 @@ describe('IndexPatternDimensionEditorPanel', () => {
       core: {} as CoreSetup,
       dimensionGroups: [],
       groupId: 'a',
+      isFullscreen: false,
+      toggleFullscreen: jest.fn(),
     };
 
     jest.clearAllMocks();
@@ -500,10 +502,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
       comboBox.prop('onChange')!([option]);
     });
 
-    expect(setState.mock.calls[0]).toEqual([
-      expect.any(Function),
-      { shouldRemoveDimension: false, shouldReplaceDimension: true },
-    ]);
+    expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
     expect(setState.mock.calls[0][0](defaultProps.state)).toEqual({
       ...initialState,
       layers: {
@@ -535,10 +534,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
       comboBox.prop('onChange')!([option]);
     });
 
-    expect(setState.mock.calls[0]).toEqual([
-      expect.any(Function),
-      { shouldRemoveDimension: false, shouldReplaceDimension: true },
-    ]);
+    expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
     expect(setState.mock.calls[0][0](defaultProps.state)).toEqual({
       ...state,
       layers: {
@@ -569,10 +565,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
       wrapper.find('button[data-test-subj="lns-indexPatternDimension-min"]').simulate('click');
     });
 
-    expect(setState.mock.calls[0]).toEqual([
-      expect.any(Function),
-      { shouldRemoveDimension: false, shouldReplaceDimension: true },
-    ]);
+    expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
     expect(setState.mock.calls[0][0](state)).toEqual({
       ...state,
       layers: {
@@ -643,10 +636,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
       wrapper.find('button[data-test-subj="lns-indexPatternDimension-min"]').simulate('click');
     });
 
-    expect(setState.mock.calls[0]).toEqual([
-      expect.any(Function),
-      { shouldRemoveDimension: false, shouldReplaceDimension: true },
-    ]);
+    expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
     expect(setState.mock.calls[0][0](state)).toEqual({
       ...state,
       layers: {
@@ -681,10 +671,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
       wrapper.find('button[data-test-subj="lns-indexPatternDimension-min"]').simulate('click');
     });
 
-    expect(setState.mock.calls[0]).toEqual([
-      expect.any(Function),
-      { shouldRemoveDimension: false, shouldReplaceDimension: true },
-    ]);
+    expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
     expect(setState.mock.calls[0][0](state)).toEqual({
       ...state,
       layers: {
@@ -750,10 +737,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
           .simulate('click');
       });
 
-      expect(setState.mock.calls[0]).toEqual([
-        expect.any(Function),
-        { shouldRemoveDimension: false, shouldReplaceDimension: true },
-      ]);
+      expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
       expect(setState.mock.calls[0][0](state)).toEqual({
         ...state,
         layers: {
@@ -879,7 +863,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
 
       expect(setState.mock.calls[0]).toEqual([
         expect.any(Function),
-        { shouldRemoveDimension: false, shouldReplaceDimension: false },
+        { isDimensionComplete: false },
       ]);
       expect(setState.mock.calls[0][0](state)).toEqual({
         ...state,
@@ -948,7 +932,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
       // Now check that the dimension gets cleaned up on state update
       expect(setState.mock.calls[0]).toEqual([
         expect.any(Function),
-        { shouldRemoveDimension: false, shouldReplaceDimension: false },
+        { isDimensionComplete: false },
       ]);
       expect(setState.mock.calls[0][0](state)).toEqual({
         ...state,
@@ -1042,10 +1026,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
       });
 
       expect(setState.mock.calls.length).toEqual(2);
-      expect(setState.mock.calls[1]).toEqual([
-        expect.any(Function),
-        { shouldRemoveDimension: false, shouldReplaceDimension: true },
-      ]);
+      expect(setState.mock.calls[1]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
       expect(setState.mock.calls[1][0](state)).toEqual({
         ...state,
         layers: {
@@ -1143,10 +1124,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
         .find('[data-test-subj="indexPattern-time-scaling-enable"]')
         .hostNodes()
         .simulate('click');
-      expect(setState.mock.calls[0]).toEqual([
-        expect.any(Function),
-        { shouldRemoveDimension: false, shouldReplaceDimension: true },
-      ]);
+      expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
       expect(setState.mock.calls[0][0](props.state)).toEqual({
         ...props.state,
         layers: {
@@ -1175,10 +1153,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
       wrapper
         .find('button[data-test-subj="lns-indexPatternDimension-count incompatible"]')
         .simulate('click');
-      expect(setState.mock.calls[0]).toEqual([
-        expect.any(Function),
-        { shouldRemoveDimension: false, shouldReplaceDimension: true },
-      ]);
+      expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
       expect(setState.mock.calls[0][0](props.state)).toEqual({
         ...props.state,
         layers: {
@@ -1205,10 +1180,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
       });
       wrapper = mount(<IndexPatternDimensionEditorComponent {...props} />);
       wrapper.find('button[data-test-subj="lns-indexPatternDimension-average"]').simulate('click');
-      expect(setState.mock.calls[0]).toEqual([
-        expect.any(Function),
-        { shouldRemoveDimension: false, shouldReplaceDimension: true },
-      ]);
+      expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
       expect(setState.mock.calls[0][0](props.state)).toEqual({
         ...props.state,
         layers: {
@@ -1239,10 +1211,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
         .prop('onChange')!(({
         target: { value: 'h' },
       } as unknown) as ChangeEvent<HTMLSelectElement>);
-      expect(setState.mock.calls[0]).toEqual([
-        expect.any(Function),
-        { shouldRemoveDimension: false, shouldReplaceDimension: true },
-      ]);
+      expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
       expect(setState.mock.calls[0][0](props.state)).toEqual({
         ...props.state,
         layers: {
@@ -1269,10 +1238,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
         .prop('onChange')!(({
         target: { value: 'h' },
       } as unknown) as ChangeEvent<HTMLSelectElement>);
-      expect(setState.mock.calls[0]).toEqual([
-        expect.any(Function),
-        { shouldRemoveDimension: false, shouldReplaceDimension: true },
-      ]);
+      expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
       expect(setState.mock.calls[0][0](props.state)).toEqual({
         ...props.state,
         layers: {
@@ -1300,10 +1266,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
         // eslint-disable-next-line @typescript-eslint/no-explicit-any
         {} as any
       );
-      expect(setState.mock.calls[0]).toEqual([
-        expect.any(Function),
-        { shouldRemoveDimension: false, shouldReplaceDimension: true },
-      ]);
+      expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
       expect(setState.mock.calls[0][0](props.state)).toEqual({
         ...props.state,
         layers: {
@@ -1593,10 +1556,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
         .find('[data-test-subj="indexPattern-filter-by-enable"]')
         .hostNodes()
         .simulate('click');
-      expect(setState.mock.calls[0]).toEqual([
-        expect.any(Function),
-        { shouldRemoveDimension: false, shouldReplaceDimension: true },
-      ]);
+      expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
       expect(setState.mock.calls[0][0](props.state)).toEqual({
         ...props.state,
         layers: {
@@ -1627,10 +1587,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
       wrapper
         .find('button[data-test-subj="lns-indexPatternDimension-count incompatible"]')
         .simulate('click');
-      expect(setState.mock.calls[0]).toEqual([
-        expect.any(Function),
-        { shouldRemoveDimension: false, shouldReplaceDimension: true },
-      ]);
+      expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
       expect(setState.mock.calls[0][0](props.state)).toEqual({
         ...props.state,
         layers: {
@@ -1656,10 +1613,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
         language: 'kuery',
         query: 'c: d',
       });
-      expect(setState.mock.calls[0]).toEqual([
-        expect.any(Function),
-        { shouldRemoveDimension: false, shouldReplaceDimension: true },
-      ]);
+      expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
       expect(setState.mock.calls[0][0](props.state)).toEqual({
         ...props.state,
         layers: {
@@ -1688,10 +1642,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
         // eslint-disable-next-line @typescript-eslint/no-explicit-any
         {} as any
       );
-      expect(setState.mock.calls[0]).toEqual([
-        expect.any(Function),
-        { shouldRemoveDimension: false, shouldReplaceDimension: true },
-      ]);
+      expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
       expect(setState.mock.calls[0][0](props.state)).toEqual({
         ...props.state,
         layers: {
@@ -1743,10 +1694,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
 
     wrapper.find('button[data-test-subj="lns-indexPatternDimension-average"]').simulate('click');
 
-    expect(setState.mock.calls[0]).toEqual([
-      expect.any(Function),
-      { shouldRemoveDimension: false, shouldReplaceDimension: false },
-    ]);
+    expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: false }]);
     expect(setState.mock.calls[0][0](defaultProps.state)).toEqual({
       ...state,
       layers: {
@@ -1810,10 +1758,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
 
     wrapper.find('button[data-test-subj="lns-indexPatternDimension-average"]').simulate('click');
 
-    expect(setState.mock.calls[0]).toEqual([
-      expect.any(Function),
-      { shouldRemoveDimension: false, shouldReplaceDimension: true },
-    ]);
+    expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
     expect(setState.mock.calls[0][0](initialState)).toEqual({
       ...initialState,
       layers: {
@@ -1838,10 +1783,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
 
     wrapper.find('button[data-test-subj="lns-indexPatternDimension-count"]').simulate('click');
 
-    expect(setState.mock.calls[0]).toEqual([
-      expect.any(Function),
-      { shouldRemoveDimension: false, shouldReplaceDimension: true },
-    ]);
+    expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
     expect(setState.mock.calls[0][0](state)).toEqual({
       ...state,
       layers: {
@@ -1975,10 +1917,7 @@ describe('IndexPatternDimensionEditorPanel', () => {
       comboBox.prop('onChange')!([option]);
     });
 
-    expect(setState.mock.calls[0]).toEqual([
-      expect.any(Function),
-      { shouldRemoveDimension: false, shouldReplaceDimension: true },
-    ]);
+    expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]);
     expect(setState.mock.calls[0][0](defaultProps.state)).toEqual({
       ...state,
       layers: {
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/droppable.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/droppable.test.ts
index a77a980257c88..56d255ec02227 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/droppable.test.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/droppable.test.ts
@@ -284,6 +284,8 @@ describe('IndexPatternDimensionEditorPanel', () => {
       } as unknown) as DataPublicPluginStart,
       core: {} as CoreSetup,
       dimensionGroups: [],
+      isFullscreen: false,
+      toggleFullscreen: () => {},
     };
 
     jest.clearAllMocks();
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx
index 3a57579583c90..ff10810208e70 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx
@@ -5,7 +5,7 @@
  * 2.0.
  */
 
-import React, { useState } from 'react';
+import React, { useCallback, useMemo, useState } from 'react';
 import { i18n } from '@kbn/i18n';
 import { EuiFormRow, EuiComboBox, EuiSpacer, EuiRange } from '@elastic/eui';
 import { IndexPatternColumn } from '../indexpattern';
@@ -28,6 +28,13 @@ const supportedFormats: Record<string, { title: string }> = {
   },
 };
 
+const defaultOption = {
+  value: '',
+  label: i18n.translate('xpack.lens.indexPattern.defaultFormatLabel', {
+    defaultMessage: 'Default',
+  }),
+};
+
 interface FormatSelectorProps {
   selectedColumn: IndexPatternColumn;
   onChange: (newFormat?: { id: string; params?: Record<string, unknown> }) => void;
@@ -37,6 +44,8 @@ interface State {
   decimalPlaces: number;
 }
 
+const singleSelectionOption = { asPlainText: true };
+
 export function FormatSelector(props: FormatSelectorProps) {
   const { selectedColumn, onChange } = props;
 
@@ -51,13 +60,6 @@ export function FormatSelector(props: FormatSelectorProps) {
 
   const selectedFormat = currentFormat?.id ? supportedFormats[currentFormat.id] : undefined;
 
-  const defaultOption = {
-    value: '',
-    label: i18n.translate('xpack.lens.indexPattern.defaultFormatLabel', {
-      defaultMessage: 'Default',
-    }),
-  };
-
   const label = i18n.translate('xpack.lens.indexPattern.columnFormatLabel', {
     defaultMessage: 'Value format',
   });
@@ -66,6 +68,48 @@ export function FormatSelector(props: FormatSelectorProps) {
     defaultMessage: 'Decimals',
   });
 
+  const stableOptions = useMemo(
+    () => [
+      defaultOption,
+      ...Object.entries(supportedFormats).map(([id, format]) => ({
+        value: id,
+        label: format.title ?? id,
+      })),
+    ],
+    []
+  );
+
+  const onChangeWrapped = useCallback(
+    (choices) => {
+      if (choices.length === 0) {
+        return;
+      }
+
+      if (!choices[0].value) {
+        onChange();
+        return;
+      }
+      onChange({
+        id: choices[0].value,
+        params: { decimals: state.decimalPlaces },
+      });
+    },
+    [onChange, state.decimalPlaces]
+  );
+
+  const currentOption = useMemo(
+    () =>
+      currentFormat
+        ? [
+            {
+              value: currentFormat.id,
+              label: selectedFormat?.title ?? currentFormat.id,
+            },
+          ]
+        : [defaultOption],
+    [currentFormat, selectedFormat?.title]
+  );
+
   return (
     <>
       <EuiFormRow label={label} display="columnCompressed" fullWidth>
@@ -76,38 +120,10 @@ export function FormatSelector(props: FormatSelectorProps) {
             isClearable={false}
             data-test-subj="indexPattern-dimension-format"
             aria-label={label}
-            singleSelection={{ asPlainText: true }}
-            options={[
-              defaultOption,
-              ...Object.entries(supportedFormats).map(([id, format]) => ({
-                value: id,
-                label: format.title ?? id,
-              })),
-            ]}
-            selectedOptions={
-              currentFormat
-                ? [
-                    {
-                      value: currentFormat.id,
-                      label: selectedFormat?.title ?? currentFormat.id,
-                    },
-                  ]
-                : [defaultOption]
-            }
-            onChange={(choices) => {
-              if (choices.length === 0) {
-                return;
-              }
-
-              if (!choices[0].value) {
-                onChange();
-                return;
-              }
-              onChange({
-                id: choices[0].value,
-                params: { decimals: state.decimalPlaces },
-              });
-            }}
+            singleSelection={singleSelectionOption}
+            options={stableOptions}
+            selectedOptions={currentOption}
+            onChange={onChangeWrapped}
           />
           {currentFormat ? (
             <>
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/operation_support.ts b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/operation_support.ts
index 504aa0912f9cc..7a7297e77bcf2 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/operation_support.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/operation_support.ts
@@ -5,9 +5,10 @@
  * 2.0.
  */
 
-import { DatasourceDimensionDropProps } from '../../types';
+import memoizeOne from 'memoize-one';
+import { DatasourceDimensionDropProps, OperationMetadata } from '../../types';
 import { OperationType } from '../indexpattern';
-import { memoizedGetAvailableOperationsByMetadata } from '../operations';
+import { memoizedGetAvailableOperationsByMetadata, OperationFieldTuple } from '../operations';
 import { IndexPatternPrivateState } from '../types';
 
 export interface OperationSupportMatrix {
@@ -21,17 +22,16 @@ type Props = Pick<
   'layerId' | 'columnId' | 'state' | 'filterOperations'
 >;
 
-// TODO: the support matrix should be available outside of the dimension panel
-
-// TODO: This code has historically been memoized, as a potentially performance
-// sensitive task. If we can add memoization without breaking the behavior, we should.
-export const getOperationSupportMatrix = (props: Props): OperationSupportMatrix => {
-  const layerId = props.layerId;
-  const currentIndexPattern = props.state.indexPatterns[props.state.layers[layerId].indexPatternId];
-
-  const filteredOperationsByMetadata = memoizedGetAvailableOperationsByMetadata(
-    currentIndexPattern
-  ).filter((operation) => props.filterOperations(operation.operationMetaData));
+function computeOperationMatrix(
+  operationsByMetadata: Array<{
+    operationMetaData: OperationMetadata;
+    operations: OperationFieldTuple[];
+  }>,
+  filterOperations: (operation: OperationMetadata) => boolean
+) {
+  const filteredOperationsByMetadata = operationsByMetadata.filter((operation) =>
+    filterOperations(operation.operationMetaData)
+  );
 
   const supportedOperationsByField: Partial<Record<string, Set<OperationType>>> = {};
   const supportedOperationsWithoutField: Set<OperationType> = new Set();
@@ -59,4 +59,16 @@ export const getOperationSupportMatrix = (props: Props): OperationSupportMatrix
     operationWithoutField: supportedOperationsWithoutField,
     fieldByOperation: supportedFieldsByOperation,
   };
+}
+
+// memoize based on latest execution. It supports multiple args
+const memoizedComputeOperationsMatrix = memoizeOne(computeOperationMatrix);
+
+// TODO: the support matrix should be available outside of the dimension panel
+export const getOperationSupportMatrix = (props: Props): OperationSupportMatrix => {
+  const layerId = props.layerId;
+  const currentIndexPattern = props.state.indexPatterns[props.state.layers[layerId].indexPatternId];
+
+  const operationsByMetadata = memoizedGetAvailableOperationsByMetadata(currentIndexPattern);
+  return memoizedComputeOperationsMatrix(operationsByMetadata, props.filterOperations);
 };
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx
index 645b6bfe70a97..fd3ad9a4e5dd5 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx
@@ -51,6 +51,9 @@ describe('reference editor', () => {
       http: {} as HttpSetup,
       data: {} as DataPublicPluginStart,
       dimensionGroups: [],
+      isFullscreen: false,
+      toggleFullscreen: jest.fn(),
+      setIsCloseable: jest.fn(),
     };
   }
 
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.tsx
index c473be05ba315..b0cdf96f928f9 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.tsx
@@ -47,10 +47,14 @@ export interface ReferenceEditorProps {
     setter: IndexPatternLayer | ((prevLayer: IndexPatternLayer) => IndexPatternLayer)
   ) => void;
   currentIndexPattern: IndexPattern;
+
   existingFields: IndexPatternPrivateState['existingFields'];
   dateRange: DateRange;
   labelAppend?: EuiFormRowProps['labelAppend'];
   dimensionGroups: VisualizationDimensionGroupConfig[];
+  isFullscreen: boolean;
+  toggleFullscreen: () => void;
+  setIsCloseable: (isCloseable: boolean) => void;
 
   // Services
   uiSettings: IUiSettingsClient;
@@ -72,6 +76,9 @@ export function ReferenceEditor(props: ReferenceEditorProps) {
     dateRange,
     labelAppend,
     dimensionGroups,
+    isFullscreen,
+    toggleFullscreen,
+    setIsCloseable,
     ...services
   } = props;
 
@@ -347,6 +354,9 @@ export function ReferenceEditor(props: ReferenceEditorProps) {
               indexPattern={currentIndexPattern}
               dateRange={dateRange}
               operationDefinitionMap={operationDefinitionMap}
+              isFullscreen={isFullscreen}
+              toggleFullscreen={toggleFullscreen}
+              setIsCloseable={setIsCloseable}
               {...services}
             />
           </>
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx
index 7cb49de15c066..bc2184bd9edb7 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx
@@ -323,6 +323,11 @@ export function getIndexPatternDatasource({
         domElement
       );
     },
+
+    canCloseDimensionEditor: (state) => {
+      return !state.isDimensionClosePrevented;
+    },
+
     getDropProps,
     onDrop,
 
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx
index 864a3a6f089db..93ea3069894d3 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx
@@ -16,6 +16,7 @@ import {
 } from './indexpattern_suggestions';
 import { documentField } from './document_field';
 import { getFieldByNameFactory } from './pure_helpers';
+import { isEqual } from 'lodash';
 
 jest.mock('./loader');
 jest.mock('../id_generator');
@@ -867,10 +868,7 @@ describe('IndexPattern Data Source suggestions', () => {
           searchable: true,
         });
 
-        expect(suggestions).toHaveLength(1);
-        // Check that the suggestion is a single metric
-        expect(suggestions[0].table.columns).toHaveLength(1);
-        expect(suggestions[0].table.columns[0].operation.isBucketed).toBeFalsy();
+        expect(suggestions).toHaveLength(0);
       });
 
       it('appends a terms column with default size on string field', () => {
@@ -1025,6 +1023,24 @@ describe('IndexPattern Data Source suggestions', () => {
         expect(suggestions).not.toContain(expect.objectContaining({ changeType: 'extended' }));
       });
 
+      it('skips metric only suggestion when the field is already in use', () => {
+        const initialState = stateWithNonEmptyTables();
+        const suggestions = getDatasourceSuggestionsForField(initialState, '1', {
+          name: 'bytes',
+          displayName: 'bytes',
+          type: 'number',
+          aggregatable: true,
+          searchable: true,
+        });
+
+        expect(
+          suggestions.some(
+            (suggestion) =>
+              suggestion.table.changeType === 'initial' && suggestion.table.columns.length === 1
+          )
+        ).toBeFalsy();
+      });
+
       it('skips duplicates when the document-specific field is already in use', () => {
         const initialState = stateWithNonEmptyTables();
         const modifiedState: IndexPatternPrivateState = {
@@ -2344,7 +2360,7 @@ describe('IndexPattern Data Source suggestions', () => {
         );
       });
 
-      it('will skip a reduced suggestion when handling multiple references', () => {
+      it('will create reduced suggestions with all referenced children when handling references', () => {
         const initialState = testInitialState();
         const state: IndexPatternPrivateState = {
           ...initialState,
@@ -2352,7 +2368,17 @@ describe('IndexPattern Data Source suggestions', () => {
             ...initialState.layers,
             first: {
               ...initialState.layers.first,
-              columnOrder: ['date', 'metric', 'metric2', 'ref', 'ref2'],
+              columnOrder: [
+                'date',
+                'metric',
+                'metric2',
+                'ref',
+                'ref2',
+                'ref3',
+                'ref4',
+                'metric3',
+                'metric4',
+              ],
 
               columns: {
                 date: {
@@ -2384,6 +2410,20 @@ describe('IndexPattern Data Source suggestions', () => {
                   operationType: 'count',
                   sourceField: 'Records',
                 },
+                metric3: {
+                  label: '',
+                  dataType: 'number',
+                  isBucketed: false,
+                  operationType: 'count',
+                  sourceField: 'Records',
+                },
+                metric4: {
+                  label: '',
+                  dataType: 'number',
+                  isBucketed: false,
+                  operationType: 'count',
+                  sourceField: 'Records',
+                },
                 ref2: {
                   label: '',
                   dataType: 'number',
@@ -2391,22 +2431,163 @@ describe('IndexPattern Data Source suggestions', () => {
                   operationType: 'cumulative_sum',
                   references: ['metric2'],
                 },
+                ref3: {
+                  label: '',
+                  dataType: 'number',
+                  isBucketed: false,
+                  operationType: 'math',
+                  references: ['ref4', 'metric3'],
+                  params: {
+                    tinymathAst: '',
+                  },
+                },
+                ref4: {
+                  label: '',
+                  dataType: 'number',
+                  isBucketed: false,
+                  operationType: 'math',
+                  references: ['metric4'],
+                  params: {
+                    tinymathAst: '',
+                  },
+                },
               },
             },
           },
         };
 
-        const result = getSuggestionSubset(getDatasourceSuggestionsFromCurrentState(state));
-
-        expect(result).not.toContainEqual(
-          expect.objectContaining({
-            table: expect.objectContaining({
-              changeType: 'reduced',
-            }),
-          })
-        );
+        const result = getDatasourceSuggestionsFromCurrentState(state);
+
+        // only generate suggestions for top level metrics
+        expect(
+          result.filter((suggestion) => suggestion.table.changeType === 'reduced').length
+        ).toEqual(3);
+
+        // top level "ref" column
+        expect(
+          result.some(
+            (suggestion) =>
+              suggestion.table.changeType === 'reduced' &&
+              isEqual(suggestion.state.layers.first.columnOrder, ['ref', 'metric'])
+          )
+        ).toBeTruthy();
+
+        // top level "ref2" column
+        expect(
+          result.some(
+            (suggestion) =>
+              suggestion.table.changeType === 'reduced' &&
+              isEqual(suggestion.state.layers.first.columnOrder, ['ref2', 'metric2'])
+          )
+        ).toBeTruthy();
+
+        // top level "ref3" column
+        expect(
+          result.some(
+            (suggestion) =>
+              suggestion.table.changeType === 'reduced' &&
+              isEqual(suggestion.state.layers.first.columnOrder, [
+                'ref3',
+                'ref4',
+                'metric3',
+                'metric4',
+              ])
+          )
+        ).toBeTruthy();
       });
     });
+
+    it('will leave dangling references in place', () => {
+      const initialState = testInitialState();
+      const state: IndexPatternPrivateState = {
+        ...initialState,
+        layers: {
+          ...initialState.layers,
+          first: {
+            ...initialState.layers.first,
+            columnOrder: ['date', 'ref'],
+
+            columns: {
+              date: {
+                label: '',
+                dataType: 'date',
+                isBucketed: true,
+                operationType: 'date_histogram',
+                sourceField: 'timestamp',
+                params: { interval: 'auto' },
+              },
+              ref: {
+                label: '',
+                dataType: 'number',
+                isBucketed: false,
+                operationType: 'cumulative_sum',
+                references: ['non_existing_metric'],
+              },
+            },
+          },
+        },
+      };
+
+      const result = getDatasourceSuggestionsFromCurrentState(state);
+
+      // only generate suggestions for top level metrics
+      expect(
+        result.filter((suggestion) => suggestion.table.changeType === 'reduced').length
+      ).toEqual(1);
+
+      // top level "ref" column
+      expect(
+        result.some(
+          (suggestion) =>
+            suggestion.table.changeType === 'reduced' &&
+            isEqual(suggestion.state.layers.first.columnOrder, ['ref'])
+        )
+      ).toBeTruthy();
+    });
+
+    it('will not suggest reduced tables if there is just a referenced top level metric', () => {
+      const initialState = testInitialState();
+      const state: IndexPatternPrivateState = {
+        ...initialState,
+        layers: {
+          ...initialState.layers,
+          first: {
+            ...initialState.layers.first,
+            columnOrder: ['ref', 'metric'],
+
+            columns: {
+              ref: {
+                label: '',
+                dataType: 'number',
+                isBucketed: false,
+                operationType: 'math',
+                params: {
+                  tinymathAst: '',
+                },
+                references: ['metric'],
+              },
+              metric: {
+                label: '',
+                dataType: 'number',
+                isBucketed: false,
+                operationType: 'count',
+                sourceField: 'Records',
+              },
+            },
+          },
+        },
+      };
+
+      const result = getDatasourceSuggestionsFromCurrentState(state);
+
+      expect(
+        result.filter((suggestion) => suggestion.table.changeType === 'unchanged').length
+      ).toEqual(1);
+
+      expect(
+        result.filter((suggestion) => suggestion.table.changeType === 'reduced').length
+      ).toEqual(0);
+    });
   });
 });
 
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts
index 803ba9f5bae5d..cff036db4813b 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts
@@ -5,7 +5,7 @@
  * 2.0.
  */
 
-import { flatten, minBy, pick, mapValues } from 'lodash';
+import { flatten, minBy, pick, mapValues, partition } from 'lodash';
 import { i18n } from '@kbn/i18n';
 import { generateId } from '../id_generator';
 import { DatasourceSuggestion, TableChangeType } from '../types';
@@ -20,6 +20,7 @@ import {
   OperationType,
   getExistingColumnGroups,
   isReferenced,
+  getReferencedColumnIds,
 } from './operations';
 import { hasField } from './utils';
 import {
@@ -254,9 +255,11 @@ function getExistingLayerSuggestionsForField(
     }
   }
 
-  const metricSuggestion = createMetricSuggestion(indexPattern, layerId, state, field);
-  if (metricSuggestion) {
-    suggestions.push(metricSuggestion);
+  if (!fieldInUse) {
+    const metricSuggestion = createMetricSuggestion(indexPattern, layerId, state, field);
+    if (metricSuggestion) {
+      suggestions.push(metricSuggestion);
+    }
   }
 
   return suggestions;
@@ -514,8 +517,11 @@ function createAlternativeMetricSuggestions(
 ) {
   const layer = state.layers[layerId];
   const suggestions: Array<DatasourceSuggestion<IndexPatternPrivateState>> = [];
+  const topLevelMetricColumns = layer.columnOrder.filter(
+    (columnId) => !isReferenced(layer, columnId)
+  );
 
-  layer.columnOrder.forEach((columnId) => {
+  topLevelMetricColumns.forEach((columnId) => {
     const column = layer.columns[columnId];
     if (!hasField(column)) {
       return;
@@ -580,11 +586,13 @@ function createSuggestionWithDefaultDateHistogram(
 function createSimplifiedTableSuggestions(state: IndexPatternPrivateState, layerId: string) {
   const layer = state.layers[layerId];
 
-  const [
-    availableBucketedColumns,
-    availableMetricColumns,
-    availableReferenceColumns,
-  ] = getExistingColumnGroups(layer);
+  const [availableBucketedColumns, availableMetricColumns] = partition(
+    layer.columnOrder,
+    (colId) => layer.columns[colId].isBucketed
+  );
+  const topLevelMetricColumns = availableMetricColumns.filter(
+    (columnId) => !isReferenced(layer, columnId)
+  );
 
   return flatten(
     availableBucketedColumns.map((_col, index) => {
@@ -593,46 +601,60 @@ function createSimplifiedTableSuggestions(state: IndexPatternPrivateState, layer
       const allMetricsSuggestion = {
         ...layer,
         columnOrder: [...bucketedColumns, ...availableMetricColumns],
+        noBuckets: false,
       };
 
-      if (availableBucketedColumns.length <= 1 || availableReferenceColumns.length) {
-        // Don't simplify when dealing with single-bucket table. Also don't break
-        // reference-based columns by removing buckets.
+      if (availableBucketedColumns.length <= 1) {
+        // Don't simplify when dealing with single-bucket table.
         return [];
-      } else if (availableMetricColumns.length > 1) {
-        return [{ ...layer, columnOrder: [...bucketedColumns, availableMetricColumns[0]] }];
+      } else if (topLevelMetricColumns.length > 1) {
+        return [
+          {
+            ...layer,
+            columnOrder: [
+              ...bucketedColumns,
+              topLevelMetricColumns[0],
+              ...getReferencedColumnIds(layer, topLevelMetricColumns[0]),
+            ],
+            noBuckets: false,
+          },
+        ];
       } else {
         return allMetricsSuggestion;
       }
     })
   )
     .concat(
-      availableReferenceColumns.length
-        ? []
-        : availableMetricColumns.map((columnId) => {
-            return { ...layer, columnOrder: [columnId] };
+      // if there is just a single top level metric, the unchanged suggestion will take care of this case - only split up if there are multiple metrics or at least one bucket
+      availableBucketedColumns.length > 0 || topLevelMetricColumns.length > 1
+        ? topLevelMetricColumns.map((columnId) => {
+            return {
+              ...layer,
+              columnOrder: [columnId, ...getReferencedColumnIds(layer, columnId)],
+              noBuckets: true,
+            };
           })
+        : []
     )
-    .map((updatedLayer) => {
+    .map(({ noBuckets, ...updatedLayer }) => {
       return buildSuggestion({
         state,
         layerId,
         updatedLayer,
         changeType: 'reduced',
-        label:
-          updatedLayer.columnOrder.length === 1
-            ? getMetricSuggestionTitle(updatedLayer, availableMetricColumns.length === 1)
-            : undefined,
+        label: noBuckets
+          ? getMetricSuggestionTitle(updatedLayer, availableMetricColumns.length === 1)
+          : undefined,
       });
     });
 }
 
-function getMetricSuggestionTitle(layer: IndexPatternLayer, onlyMetric: boolean) {
+function getMetricSuggestionTitle(layer: IndexPatternLayer, onlySimpleMetric: boolean) {
   const { operationType, label } = layer.columns[layer.columnOrder[0]];
   return i18n.translate('xpack.lens.indexpattern.suggestions.overallLabel', {
     defaultMessage: '{operation} overall',
     values: {
-      operation: onlyMetric ? operationDefinitionMap[operationType].displayName : label,
+      operation: onlySimpleMetric ? operationDefinitionMap[operationType].displayName : label,
     },
     description:
       'Title of a suggested chart containing only a single numerical metric calculated over all available data',
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/__mocks__/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/__mocks__/index.ts
index 40d7e3ef94ad6..d6429fb67e9a1 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/__mocks__/index.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/__mocks__/index.ts
@@ -17,6 +17,7 @@ jest.spyOn(actualHelpers, 'insertOrReplaceColumn');
 jest.spyOn(actualHelpers, 'insertNewColumn');
 jest.spyOn(actualHelpers, 'replaceColumn');
 jest.spyOn(actualHelpers, 'getErrorMessages');
+jest.spyOn(actualHelpers, 'getColumnOrder');
 
 export const {
   getAvailableOperationsByMetadata,
@@ -48,6 +49,8 @@ export const {
   resetIncomplete,
   isOperationAllowedAsReference,
   canTransition,
+  isColumnValidAsReference,
+  getManagedColumnsFrom,
 } = actualHelpers;
 
 export const { adjustTimeScaleLabelSuffix, DEFAULT_TIME_SCALE } = actualTimeScaleUtils;
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/counter_rate.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/counter_rate.tsx
index 823ec3eb58a92..396eae9b39c41 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/counter_rate.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/counter_rate.tsx
@@ -121,5 +121,23 @@ export const counterRateOperation: OperationDefinition<
   },
   timeScalingMode: 'mandatory',
   filterable: true,
+  documentation: {
+    section: 'calculation',
+    signature: i18n.translate('xpack.lens.indexPattern.counterRate.signature', {
+      defaultMessage: 'metric: number',
+    }),
+    description: i18n.translate('xpack.lens.indexPattern.counterRate.documentation', {
+      defaultMessage: `
+Calculates the rate of an ever increasing counter. This function will only yield helpful results on counter metric fields which contain a measurement of some kind monotonically growing over time.
+If the value does get smaller, it will interpret this as a counter reset. To get most precise results, \`counter_rate\` should be calculated on the \`max\` of a field.
+
+This calculation will be done separately for separate series defined by filters or top values dimensions.
+It uses the current interval when used in Formula.
+
+Example: Visualize the rate of bytes received over time by a memcached server:
+\`counter_rate(max(memcached.stats.read.bytes))\`
+      `,
+    }),
+  },
   shiftable: true,
 };
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/cumulative_sum.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/cumulative_sum.tsx
index c4f01e27be886..f39e5587b398c 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/cumulative_sum.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/cumulative_sum.tsx
@@ -117,5 +117,21 @@ export const cumulativeSumOperation: OperationDefinition<
     )?.join(', ');
   },
   filterable: true,
+  documentation: {
+    section: 'calculation',
+    signature: i18n.translate('xpack.lens.indexPattern.cumulative_sum.signature', {
+      defaultMessage: 'metric: number',
+    }),
+    description: i18n.translate('xpack.lens.indexPattern.cumulativeSum.documentation', {
+      defaultMessage: `
+Calculates the cumulative sum of a metric over time, adding all previous values of a series to each value. To use this function, you need to configure a date histogram dimension as well.
+
+This calculation will be done separately for separate series defined by filters or top values dimensions.
+
+Example: Visualize the received bytes accumulated over time:
+\`cumulative_sum(sum(bytes))\`
+      `,
+    }),
+  },
   shiftable: true,
 };
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/differences.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/differences.tsx
index 7c48b5742b8db..e103acd9ab677 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/differences.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/differences.tsx
@@ -109,5 +109,22 @@ export const derivativeOperation: OperationDefinition<
   },
   timeScalingMode: 'optional',
   filterable: true,
+  documentation: {
+    section: 'calculation',
+    signature: i18n.translate('xpack.lens.indexPattern.differences.signature', {
+      defaultMessage: 'metric: number',
+    }),
+    description: i18n.translate('xpack.lens.indexPattern.differences.documentation', {
+      defaultMessage: `
+Calculates the difference to the last value of a metric over time. To use this function, you need to configure a date histogram dimension as well.
+Differences requires the data to be sequential. If your data is empty when using differences, try increasing the date histogram interval.
+
+This calculation will be done separately for separate series defined by filters or top values dimensions.
+
+Example: Visualize the change in bytes received over time:
+\`differences(sum(bytes))\`
+      `,
+    }),
+  },
   shiftable: true,
 };
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/moving_average.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/moving_average.tsx
index a3d0241d4887e..ee305bc043f1b 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/moving_average.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/moving_average.tsx
@@ -65,7 +65,9 @@ export const movingAverageOperation: OperationDefinition<
       validateMetadata: (meta) => meta.dataType === 'number' && !meta.isBucketed,
     },
   ],
-  operationParams: [{ name: 'window', type: 'number', required: true }],
+  operationParams: [
+    { name: 'window', type: 'number', required: false, defaultValue: WINDOW_DEFAULT_VALUE },
+  ],
   getPossibleOperation: (indexPattern) => {
     if (hasDateField(indexPattern)) {
       return {
@@ -130,6 +132,28 @@ export const movingAverageOperation: OperationDefinition<
   },
   timeScalingMode: 'optional',
   filterable: true,
+  documentation: {
+    section: 'calculation',
+    signature: i18n.translate('xpack.lens.indexPattern.moving_average.signature', {
+      defaultMessage: 'metric: number, [window]: number',
+    }),
+    description: i18n.translate('xpack.lens.indexPattern.movingAverage.documentation', {
+      defaultMessage: `
+Calculates the moving average of a metric over time, averaging the last n-th values to calculate the current value. To use this function, you need to configure a date histogram dimension as well.
+The default window value is {defaultValue}.
+
+This calculation will be done separately for separate series defined by filters or top values dimensions.
+
+Takes a named parameter \`window\` which specifies how many last values to include in the average calculation for the current value.
+
+Example: Smooth a line of measurements:
+\`moving_average(sum(bytes), window=5)\`
+      `,
+      values: {
+        defaultValue: WINDOW_DEFAULT_VALUE,
+      },
+    }),
+  },
   shiftable: true,
 };
 
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx
index 1911af0a6f679..4da8a3ca0eb24 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx
@@ -116,4 +116,21 @@ export const cardinalityOperation: OperationDefinition<CardinalityIndexPatternCo
       sourceField: field.name,
     };
   },
+  documentation: {
+    section: 'elasticsearch',
+    signature: i18n.translate('xpack.lens.indexPattern.cardinality.signature', {
+      defaultMessage: 'field: string',
+    }),
+    description: i18n.translate('xpack.lens.indexPattern.cardinality.documentation', {
+      defaultMessage: `
+Calculates the number of unique values of a specified field. Works for number, string, date and boolean values.
+
+Example: Calculate the number of different products:
+\`unique_count(product.name)\`
+
+Example: Calculate the number of different products from the "clothes" group:
+\`unique_count(product.name, kql='product.group=clothes')\`
+      `,
+    }),
+  },
 };
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx
index 7bf463a2095ad..79cca54952318 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx
@@ -111,5 +111,20 @@ export const countOperation: OperationDefinition<CountIndexPatternColumn, 'field
   },
   timeScalingMode: 'optional',
   filterable: true,
+  documentation: {
+    section: 'elasticsearch',
+    signature: '',
+    description: i18n.translate('xpack.lens.indexPattern.count.documentation', {
+      defaultMessage: `
+Calculates the number of documents.
+
+Example: Calculate the number of documents: 
+\`count()\`
+
+Example: Calculate the number of documents matching a certain filter:
+\`count(kql='price > 500')\`
+      `,
+    }),
+  },
   shiftable: true,
 };
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx
index 92741b9b5ed09..b18c16f48f67e 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx
@@ -98,6 +98,9 @@ const defaultOptions = {
   http: {} as HttpSetup,
   indexPattern: indexPattern1,
   operationDefinitionMap: {},
+  isFullscreen: false,
+  toggleFullscreen: jest.fn(),
+  setIsCloseable: jest.fn(),
 };
 
 describe('date_histogram', () => {
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx
index 46fddd9b1ffbf..75068817c6123 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx
@@ -28,6 +28,9 @@ const defaultProps = {
   http: {} as HttpSetup,
   indexPattern: createMockedIndexPattern(),
   operationDefinitionMap: {},
+  isFullscreen: false,
+  toggleFullscreen: jest.fn(),
+  setIsCloseable: jest.fn(),
 };
 
 // mocking random id generator function
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula.scss b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula.scss
new file mode 100644
index 0000000000000..14b3fc33efb4e
--- /dev/null
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula.scss
@@ -0,0 +1,167 @@
+.lnsFormula {
+  display: flex;
+  flex-direction: column;
+
+  .lnsIndexPatternDimensionEditor-isFullscreen & {
+    height: 100%;
+  }
+
+  & > * {
+    flex: 1;
+    min-height: 0;
+  }
+
+  & > * + * {
+    border-top: $euiBorderThin;
+  }
+}
+
+.lnsFormula__editor {
+  border-bottom: $euiBorderThin;
+
+  .lnsIndexPatternDimensionEditor-isFullscreen & {
+    border-bottom: none;
+    display: flex;
+    flex-direction: column;
+  }
+
+  & > * + * {
+    border-top: $euiBorderThin;
+  }
+}
+
+.lnsFormula__editorHeader,
+.lnsFormula__editorFooter {
+  padding: $euiSizeS;
+}
+
+.lnsFormula__editorFooter {
+  // make sure docs are rendered in front of monaco
+  z-index: 1;
+  background-color: $euiColorLightestShade;
+}
+
+.lnsFormula__editorHeaderGroup,
+.lnsFormula__editorFooterGroup {
+  display: block; // Overrides EUI's styling of `display: flex` on `EuiFlexItem` components
+}
+
+.lnsFormula__editorContent {
+  position: relative;
+  height: 201px;
+}
+
+.lnsFormula__editorPlaceholder {
+  position: absolute;
+  top: 0;
+  left: $euiSize;
+  right: 0;
+  color: $euiTextSubduedColor;
+  // Matches monaco editor
+  font-family: Menlo, Monaco, 'Courier New', monospace;
+  pointer-events: none;
+}
+
+.lnsIndexPatternDimensionEditor-isFullscreen .lnsFormula__editorContent {
+  flex: 1;
+  min-height: 201px;
+}
+
+.lnsFormula__warningText + .lnsFormula__warningText {
+  margin-top: $euiSizeS;
+  border-top: $euiBorderThin;
+  padding-top: $euiSizeS;
+}
+
+.lnsFormula__editorHelp--inline {
+  align-items: center;
+  display: flex;
+  padding: $euiSizeXS;
+
+  & > * + * {
+    margin-left: $euiSizeXS;
+  }
+}
+
+.lnsFormula__editorError {
+  white-space: nowrap;
+}
+
+.lnsFormula__docs {
+  background: $euiColorEmptyShade;
+}
+
+.lnsFormula__docs--inline {
+  display: flex;
+  flex-direction: column;
+  // make sure docs are rendered in front of monaco
+  z-index: 1;
+}
+
+.lnsFormula__docsContent {
+  .lnsFormula__docs--overlay & {
+    height: 40vh;
+    width:  #{'min(75vh, 90vw)'};
+  }
+
+  .lnsFormula__docs--inline & {
+    flex: 1;
+    min-height: 0;
+  }
+
+  & > * + * {
+    border-left: $euiBorderThin;
+  }
+}
+
+.lnsFormula__docsSidebar {
+  background: $euiColorLightestShade;
+}
+
+.lnsFormula__docsSidebarInner {
+  min-height: 0;
+
+  & > * + * {
+    border-top: $euiBorderThin;
+  }
+}
+
+.lnsFormula__docsSearch {
+  padding: $euiSizeS;
+}
+
+.lnsFormula__docsNav {
+  @include euiYScroll;
+}
+
+.lnsFormula__docsNavGroup {
+  padding: $euiSizeS;
+
+  & + & {
+    border-top: $euiBorderThin;
+  }
+}
+
+.lnsFormula__docsNavGroupLink {
+  font-weight: inherit;
+}
+
+.lnsFormula__docsText {
+  @include euiYScroll;
+  padding: $euiSize;
+}
+
+.lnsFormula__docsTextGroup,
+.lnsFormula__docsTextItem {
+  margin-top: $euiSizeXXL;
+}
+
+.lnsFormula__docsTextGroup {
+  border-top: $euiBorderThin;
+  padding-top: $euiSizeXXL;
+}
+
+.lnsFormulaOverflow {
+  // Needs to be higher than the modal and all flyouts
+  z-index: $euiZLevel9 + 1;
+}
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_editor.tsx
new file mode 100644
index 0000000000000..312ceb116dced
--- /dev/null
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_editor.tsx
@@ -0,0 +1,791 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { useCallback, useEffect, useState, useMemo } from 'react';
+import { i18n } from '@kbn/i18n';
+import {
+  EuiButtonIcon,
+  EuiButtonEmpty,
+  EuiFlexGroup,
+  EuiFlexItem,
+  EuiIcon,
+  EuiLink,
+  EuiPopover,
+  EuiText,
+  EuiToolTip,
+  EuiSpacer,
+} from '@elastic/eui';
+import useUnmount from 'react-use/lib/useUnmount';
+import { monaco } from '@kbn/monaco';
+import classNames from 'classnames';
+import { CodeEditor } from '../../../../../../../../../src/plugins/kibana_react/public';
+import type { CodeEditorProps } from '../../../../../../../../../src/plugins/kibana_react/public';
+import { useDebounceWithOptions } from '../../../../../shared_components';
+import { ParamEditorProps } from '../../index';
+import { getManagedColumnsFrom } from '../../../layer_helpers';
+import { ErrorWrapper, runASTValidation, tryToParse } from '../validation';
+import {
+  LensMathSuggestion,
+  SUGGESTION_TYPE,
+  suggest,
+  getSuggestion,
+  getSignatureHelp,
+  getHover,
+  getTokenInfo,
+  offsetToRowColumn,
+  monacoPositionToOffset,
+} from './math_completion';
+import { LANGUAGE_ID } from './math_tokenization';
+import { MemoizedFormulaHelp } from './formula_help';
+import { trackUiEvent } from '../../../../../lens_ui_telemetry';
+
+import './formula.scss';
+import { FormulaIndexPatternColumn } from '../formula';
+import { regenerateLayerFromAst } from '../parse';
+import { filterByVisibleOperation } from '../util';
+
+export const MemoizedFormulaEditor = React.memo(FormulaEditor);
+
+export function FormulaEditor({
+  layer,
+  updateLayer,
+  currentColumn,
+  columnId,
+  indexPattern,
+  operationDefinitionMap,
+  data,
+  toggleFullscreen,
+  isFullscreen,
+  setIsCloseable,
+}: ParamEditorProps<FormulaIndexPatternColumn>) {
+  const [text, setText] = useState(currentColumn.params.formula);
+  const [warnings, setWarnings] = useState<
+    Array<{ severity: monaco.MarkerSeverity; message: string }>
+  >([]);
+  const [isHelpOpen, setIsHelpOpen] = useState<boolean>(isFullscreen);
+  const [isWarningOpen, setIsWarningOpen] = useState<boolean>(false);
+  const [isWordWrapped, toggleWordWrap] = useState<boolean>(true);
+  const editorModel = React.useRef<monaco.editor.ITextModel>();
+  const overflowDiv1 = React.useRef<HTMLElement>();
+  const disposables = React.useRef<monaco.IDisposable[]>([]);
+  const editor1 = React.useRef<monaco.editor.IStandaloneCodeEditor>();
+
+  const visibleOperationsMap = useMemo(() => filterByVisibleOperation(operationDefinitionMap), [
+    operationDefinitionMap,
+  ]);
+
+  // The Monaco editor needs to have the overflowDiv in the first render. Using an effect
+  // requires a second render to work, so we are using an if statement to guarantee it happens
+  // on first render
+  if (!overflowDiv1?.current) {
+    const node1 = (overflowDiv1.current = document.createElement('div'));
+    node1.setAttribute('data-test-subj', 'lnsFormulaWidget');
+    // Monaco CSS is targeted on the monaco-editor class
+    node1.classList.add('lnsFormulaOverflow', 'monaco-editor');
+    document.body.appendChild(node1);
+  }
+
+  // Clean up the monaco editor and DOM on unmount
+  useEffect(() => {
+    const model = editorModel;
+    const allDisposables = disposables;
+    const editor1ref = editor1;
+    return () => {
+      model.current?.dispose();
+      overflowDiv1.current?.parentNode?.removeChild(overflowDiv1.current);
+      editor1ref.current?.dispose();
+      allDisposables.current?.forEach((d) => d.dispose());
+    };
+  }, []);
+
+  useUnmount(() => {
+    setIsCloseable(true);
+    // If the text is not synced, update the column.
+    if (text !== currentColumn.params.formula) {
+      updateLayer((prevLayer) => {
+        return regenerateLayerFromAst(
+          text || '',
+          prevLayer,
+          columnId,
+          currentColumn,
+          indexPattern,
+          operationDefinitionMap
+        ).newLayer;
+      });
+    }
+  });
+
+  useDebounceWithOptions(
+    () => {
+      if (!editorModel.current) return;
+
+      if (!text) {
+        setWarnings([]);
+        monaco.editor.setModelMarkers(editorModel.current, 'LENS', []);
+        if (currentColumn.params.formula) {
+          // Only submit if valid
+          const { newLayer } = regenerateLayerFromAst(
+            text || '',
+            layer,
+            columnId,
+            currentColumn,
+            indexPattern,
+            operationDefinitionMap
+          );
+          updateLayer(newLayer);
+        }
+
+        return;
+      }
+
+      let errors: ErrorWrapper[] = [];
+
+      const { root, error } = tryToParse(text, visibleOperationsMap);
+      if (error) {
+        errors = [error];
+      } else if (root) {
+        const validationErrors = runASTValidation(root, layer, indexPattern, visibleOperationsMap);
+        if (validationErrors.length) {
+          errors = validationErrors;
+        }
+      }
+
+      if (errors.length) {
+        if (currentColumn.params.isFormulaBroken) {
+          // If the formula is already broken, show the latest error message in the workspace
+          if (currentColumn.params.formula !== text) {
+            updateLayer(
+              regenerateLayerFromAst(
+                text || '',
+                layer,
+                columnId,
+                currentColumn,
+                indexPattern,
+                visibleOperationsMap
+              ).newLayer
+            );
+          }
+        }
+
+        const markers = errors.flatMap((innerError) => {
+          if (innerError.locations.length) {
+            return innerError.locations.map((location) => {
+              const startPosition = offsetToRowColumn(text, location.min);
+              const endPosition = offsetToRowColumn(text, location.max);
+              return {
+                message: innerError.message,
+                startColumn: startPosition.column + 1,
+                startLineNumber: startPosition.lineNumber,
+                endColumn: endPosition.column + 1,
+                endLineNumber: endPosition.lineNumber,
+                severity:
+                  innerError.severity === 'warning'
+                    ? monaco.MarkerSeverity.Warning
+                    : monaco.MarkerSeverity.Error,
+              };
+            });
+          } else {
+            // Parse errors return no location info
+            const startPosition = offsetToRowColumn(text, 0);
+            const endPosition = offsetToRowColumn(text, text.length - 1);
+            return [
+              {
+                message: innerError.message,
+                startColumn: startPosition.column + 1,
+                startLineNumber: startPosition.lineNumber,
+                endColumn: endPosition.column + 1,
+                endLineNumber: endPosition.lineNumber,
+                severity:
+                  innerError.severity === 'warning'
+                    ? monaco.MarkerSeverity.Warning
+                    : monaco.MarkerSeverity.Error,
+              },
+            ];
+          }
+        });
+
+        monaco.editor.setModelMarkers(editorModel.current, 'LENS', markers);
+        setWarnings(markers.map(({ severity, message }) => ({ severity, message })));
+      } else {
+        monaco.editor.setModelMarkers(editorModel.current, 'LENS', []);
+
+        // Only submit if valid
+        const { newLayer, locations } = regenerateLayerFromAst(
+          text || '',
+          layer,
+          columnId,
+          currentColumn,
+          indexPattern,
+          visibleOperationsMap
+        );
+        updateLayer(newLayer);
+
+        const managedColumns = getManagedColumnsFrom(columnId, newLayer.columns);
+        const markers: monaco.editor.IMarkerData[] = managedColumns
+          .flatMap(([id, column]) => {
+            if (locations[id]) {
+              const def = visibleOperationsMap[column.operationType];
+              if (def.getErrorMessage) {
+                const messages = def.getErrorMessage(
+                  newLayer,
+                  id,
+                  indexPattern,
+                  visibleOperationsMap
+                );
+                if (messages) {
+                  const startPosition = offsetToRowColumn(text, locations[id].min);
+                  const endPosition = offsetToRowColumn(text, locations[id].max);
+                  return [
+                    {
+                      message: messages.join(', '),
+                      startColumn: startPosition.column + 1,
+                      startLineNumber: startPosition.lineNumber,
+                      endColumn: endPosition.column + 1,
+                      endLineNumber: endPosition.lineNumber,
+                      severity: monaco.MarkerSeverity.Warning,
+                    },
+                  ];
+                }
+              }
+            }
+            return [];
+          })
+          .filter((marker) => marker);
+        setWarnings(markers.map(({ severity, message }) => ({ severity, message })));
+        monaco.editor.setModelMarkers(editorModel.current, 'LENS', markers);
+      }
+    },
+    // Make it validate on flyout open in case of a broken formula left over
+    // from a previous edit
+    { skipFirstRender: false },
+    256,
+    [text]
+  );
+
+  const errorCount = warnings.filter((marker) => marker.severity === monaco.MarkerSeverity.Error)
+    .length;
+  const warningCount = warnings.filter(
+    (marker) => marker.severity === monaco.MarkerSeverity.Warning
+  ).length;
+
+  /**
+   * The way that Monaco requests autocompletion is not intuitive, but the way we use it
+   * we fetch new suggestions in these scenarios:
+   *
+   * - If the user types one of the trigger characters, suggestions are always fetched
+   * - When the user selects the kql= suggestion, we tell Monaco to trigger new suggestions after
+   * - When the user types the first character into an empty text box, Monaco requests suggestions
+   *
+   * Monaco also triggers suggestions automatically when there are no suggestions being displayed
+   * and the user types a non-whitespace character.
+   *
+   * While suggestions are being displayed, Monaco uses an in-memory cache of the last known suggestions.
+   */
+  const provideCompletionItems = useCallback(
+    async (
+      model: monaco.editor.ITextModel,
+      position: monaco.Position,
+      context: monaco.languages.CompletionContext
+    ) => {
+      const innerText = model.getValue();
+      let aSuggestions: { list: LensMathSuggestion[]; type: SUGGESTION_TYPE } = {
+        list: [],
+        type: SUGGESTION_TYPE.FIELD,
+      };
+      const offset = monacoPositionToOffset(innerText, position);
+
+      if (context.triggerCharacter === '(') {
+        // Monaco usually inserts the end quote and reports the position is after the end quote
+        if (innerText.slice(offset - 1, offset + 1) === '()') {
+          position = position.delta(0, -1);
+        }
+        const wordUntil = model.getWordAtPosition(position.delta(0, -3));
+        if (wordUntil) {
+          // Retrieve suggestions for subexpressions
+          aSuggestions = await suggest({
+            expression: innerText,
+            zeroIndexedOffset: offset,
+            context,
+            indexPattern,
+            operationDefinitionMap: visibleOperationsMap,
+            data,
+          });
+        }
+      } else {
+        aSuggestions = await suggest({
+          expression: innerText,
+          zeroIndexedOffset: offset,
+          context,
+          indexPattern,
+          operationDefinitionMap: visibleOperationsMap,
+          data,
+        });
+      }
+
+      return {
+        suggestions: aSuggestions.list.map((s) =>
+          getSuggestion(s, aSuggestions.type, visibleOperationsMap, context.triggerCharacter)
+        ),
+      };
+    },
+    [indexPattern, visibleOperationsMap, data]
+  );
+
+  const provideSignatureHelp = useCallback(
+    async (
+      model: monaco.editor.ITextModel,
+      position: monaco.Position,
+      token: monaco.CancellationToken,
+      context: monaco.languages.SignatureHelpContext
+    ) => {
+      const innerText = model.getValue();
+      const textRange = model.getFullModelRange();
+
+      const lengthAfterPosition = model.getValueLengthInRange({
+        startLineNumber: position.lineNumber,
+        startColumn: position.column,
+        endLineNumber: textRange.endLineNumber,
+        endColumn: textRange.endColumn,
+      });
+      return getSignatureHelp(
+        model.getValue(),
+        innerText.length - lengthAfterPosition,
+        visibleOperationsMap
+      );
+    },
+    [visibleOperationsMap]
+  );
+
+  const provideHover = useCallback(
+    async (
+      model: monaco.editor.ITextModel,
+      position: monaco.Position,
+      token: monaco.CancellationToken
+    ) => {
+      const innerText = model.getValue();
+      const textRange = model.getFullModelRange();
+
+      const lengthAfterPosition = model.getValueLengthInRange({
+        startLineNumber: position.lineNumber,
+        startColumn: position.column,
+        endLineNumber: textRange.endLineNumber,
+        endColumn: textRange.endColumn,
+      });
+      return getHover(
+        model.getValue(),
+        innerText.length - lengthAfterPosition,
+        visibleOperationsMap
+      );
+    },
+    [visibleOperationsMap]
+  );
+
+  const onTypeHandler = useCallback(
+    (e: monaco.editor.IModelContentChangedEvent, editor: monaco.editor.IStandaloneCodeEditor) => {
+      if (e.isFlush || e.isRedoing || e.isUndoing) {
+        return;
+      }
+      if (e.changes.length === 1) {
+        const char = e.changes[0].text;
+        if (char !== '=' && char !== "'") {
+          return;
+        }
+        const currentPosition = e.changes[0].range;
+        if (currentPosition) {
+          const currentText = editor.getValue();
+          const offset = monacoPositionToOffset(
+            currentText,
+            new monaco.Position(currentPosition.startLineNumber, currentPosition.startColumn)
+          );
+          let tokenInfo = getTokenInfo(currentText, offset + 1);
+
+          if (!tokenInfo && char === "'") {
+            // try again this time replacing the current quote with an escaped quote
+            const line = currentText;
+            const lineEscaped = line.substring(0, offset) + "\\'" + line.substring(offset + 1);
+            tokenInfo = getTokenInfo(lineEscaped, offset + 2);
+          }
+
+          const isSingleQuoteCase = /'LENS_MATH_MARKER/;
+          // Make sure that we are only adding kql='' or lucene='', and also
+          // check that the = sign isn't inside the KQL expression like kql='='
+          if (
+            !tokenInfo ||
+            typeof tokenInfo.ast === 'number' ||
+            tokenInfo.ast.type !== 'namedArgument' ||
+            (tokenInfo.ast.name !== 'kql' && tokenInfo.ast.name !== 'lucene') ||
+            (tokenInfo.ast.value !== 'LENS_MATH_MARKER' &&
+              !isSingleQuoteCase.test(tokenInfo.ast.value))
+          ) {
+            return;
+          }
+
+          let editOperation: monaco.editor.IIdentifiedSingleEditOperation | null = null;
+          const cursorOffset = 2;
+          if (char === '=') {
+            editOperation = {
+              range: {
+                ...currentPosition,
+                // Insert after the current char
+                startColumn: currentPosition.startColumn + 1,
+                endColumn: currentPosition.startColumn + 1,
+              },
+              text: `''`,
+            };
+          }
+          if (char === "'") {
+            editOperation = {
+              range: {
+                ...currentPosition,
+                // Insert after the current char
+                startColumn: currentPosition.startColumn,
+                endColumn: currentPosition.startColumn + 1,
+              },
+              text: `\\'`,
+            };
+          }
+
+          if (editOperation) {
+            setTimeout(() => {
+              editor.executeEdits(
+                'LENS',
+                [editOperation!],
+                [
+                  // After inserting, move the cursor in between the single quotes or after the escaped quote
+                  new monaco.Selection(
+                    currentPosition.startLineNumber,
+                    currentPosition.startColumn + cursorOffset,
+                    currentPosition.startLineNumber,
+                    currentPosition.startColumn + cursorOffset
+                  ),
+                ]
+              );
+
+              // Need to move these sync to prevent race conditions between a fast user typing a single quote
+              // after an = char
+              // Timeout is required because otherwise the cursor position is not updated.
+              editor.setPosition({
+                column: currentPosition.startColumn + cursorOffset,
+                lineNumber: currentPosition.startLineNumber,
+              });
+              editor.trigger('lens', 'editor.action.triggerSuggest', {});
+            }, 0);
+          }
+        }
+      }
+    },
+    []
+  );
+
+  const codeEditorOptions: CodeEditorProps = {
+    languageId: LANGUAGE_ID,
+    value: text ?? '',
+    onChange: setText,
+    options: {
+      automaticLayout: false,
+      fontSize: 14,
+      folding: false,
+      lineNumbers: 'off',
+      scrollBeyondLastLine: false,
+      minimap: { enabled: false },
+      wordWrap: isWordWrapped ? 'on' : 'off',
+      // Disable suggestions that appear when we don't provide a default suggestion
+      wordBasedSuggestions: false,
+      autoIndent: 'brackets',
+      wrappingIndent: 'none',
+      dimension: { width: 320, height: 200 },
+      fixedOverflowWidgets: true,
+      matchBrackets: 'always',
+    },
+  };
+
+  useEffect(() => {
+    // Because the monaco model is owned by Lens, we need to manually attach and remove handlers
+    const { dispose: dispose1 } = monaco.languages.registerCompletionItemProvider(LANGUAGE_ID, {
+      triggerCharacters: ['.', '(', '=', ' ', ':', `'`],
+      provideCompletionItems,
+    });
+    const { dispose: dispose2 } = monaco.languages.registerSignatureHelpProvider(LANGUAGE_ID, {
+      signatureHelpTriggerCharacters: ['(', '='],
+      provideSignatureHelp,
+    });
+    const { dispose: dispose3 } = monaco.languages.registerHoverProvider(LANGUAGE_ID, {
+      provideHover,
+    });
+    return () => {
+      dispose1();
+      dispose2();
+      dispose3();
+    };
+  }, [provideCompletionItems, provideSignatureHelp, provideHover]);
+
+  // The Monaco editor will lazily load Monaco, which takes a render cycle to trigger. This can cause differences
+  // in the behavior of Monaco when it's first loaded and then reloaded.
+  return (
+    <div
+      className={classNames({
+        lnsIndexPatternDimensionEditor: true,
+        'lnsIndexPatternDimensionEditor-isFullscreen': isFullscreen,
+      })}
+    >
+      <div className="lnsIndexPatternDimensionEditor__section lnsIndexPatternDimensionEditor__section--shaded">
+        <div className="lnsFormula">
+          <div className="lnsFormula__editor">
+            <div className="lnsFormula__editorHeader">
+              <EuiFlexGroup alignItems="center" gutterSize="m" responsive={false}>
+                <EuiFlexItem className="lnsFormula__editorHeaderGroup">
+                  {/* TODO: Replace `bolt` with `wordWrap` icon (after latest EUI is deployed) and hook up button to enable/disable word wrapping. */}
+                  <EuiToolTip
+                    content={
+                      isWordWrapped
+                        ? i18n.translate('xpack.lens.formula.disableWordWrapLabel', {
+                            defaultMessage: 'Disable word wrap',
+                          })
+                        : i18n.translate('xpack.lens.formulaEnableWordWrapLabel', {
+                            defaultMessage: 'Enable word wrap',
+                          })
+                    }
+                    position="top"
+                  >
+                    <EuiButtonIcon
+                      iconType="bolt"
+                      display={!isWordWrapped ? 'fill' : undefined}
+                      color={'text'}
+                      aria-label={
+                        isWordWrapped
+                          ? i18n.translate('xpack.lens.formula.disableWordWrapLabel', {
+                              defaultMessage: 'Disable word wrap',
+                            })
+                          : i18n.translate('xpack.lens.formulaEnableWordWrapLabel', {
+                              defaultMessage: 'Enable word wrap',
+                            })
+                      }
+                      isSelected={!isWordWrapped}
+                      onClick={() => {
+                        editor1.current?.updateOptions({
+                          wordWrap: isWordWrapped ? 'off' : 'on',
+                        });
+                        toggleWordWrap(!isWordWrapped);
+                      }}
+                    />
+                  </EuiToolTip>
+                </EuiFlexItem>
+
+                <EuiFlexItem className="lnsFormula__editorHeaderGroup" grow={false}>
+                  {/* TODO: Replace `bolt` with `fullScreenExit` icon (after latest EUI is deployed). */}
+                  <EuiButtonEmpty
+                    onClick={() => {
+                      toggleFullscreen();
+                      // Help text opens when entering full screen, and closes when leaving full screen
+                      setIsHelpOpen(!isFullscreen);
+                      trackUiEvent('toggle_formula_fullscreen');
+                    }}
+                    iconType={isFullscreen ? 'bolt' : 'fullScreen'}
+                    size="xs"
+                    color="text"
+                    flush="right"
+                    data-test-subj="lnsFormula-fullscreen"
+                  >
+                    {isFullscreen
+                      ? i18n.translate('xpack.lens.formula.fullScreenExitLabel', {
+                          defaultMessage: 'Collapse',
+                        })
+                      : i18n.translate('xpack.lens.formula.fullScreenEnterLabel', {
+                          defaultMessage: 'Expand',
+                        })}
+                  </EuiButtonEmpty>
+                </EuiFlexItem>
+              </EuiFlexGroup>
+            </div>
+
+            <div className="lnsFormula__editorContent">
+              <CodeEditor
+                {...codeEditorOptions}
+                options={{
+                  ...codeEditorOptions.options,
+                  // Shared model and overflow node
+                  overflowWidgetsDomNode: overflowDiv1.current,
+                }}
+                editorDidMount={(editor) => {
+                  editor1.current = editor;
+                  const model = editor.getModel();
+                  if (model) {
+                    editorModel.current = model;
+                  }
+                  disposables.current.push(
+                    editor.onDidFocusEditorWidget(() => {
+                      setTimeout(() => {
+                        setIsCloseable(false);
+                      });
+                    })
+                  );
+                  disposables.current.push(
+                    editor.onDidBlurEditorWidget(() => {
+                      setTimeout(() => {
+                        setIsCloseable(true);
+                      });
+                    })
+                  );
+                  // If we ever introduce a second Monaco editor, we need to toggle
+                  // the typing handler to the active editor to maintain the cursor
+                  disposables.current.push(
+                    editor.onDidChangeModelContent((e) => {
+                      onTypeHandler(e, editor);
+                    })
+                  );
+                }}
+              />
+
+              {!text ? (
+                <div className="lnsFormula__editorPlaceholder">
+                  <EuiText color="subdued" size="s">
+                    {i18n.translate('xpack.lens.formulaPlaceholderText', {
+                      defaultMessage: 'Type a formula by combining functions with math, like:',
+                    })}
+                  </EuiText>
+                  <EuiSpacer size="s" />
+                  <pre>count() + 1</pre>
+                </div>
+              ) : null}
+            </div>
+
+            <div className="lnsFormula__editorFooter">
+              <EuiFlexGroup alignItems="center" gutterSize="m" responsive={false}>
+                <EuiFlexItem className="lnsFormula__editorFooterGroup">
+                  {isFullscreen ? (
+                    <EuiToolTip
+                      content={
+                        isHelpOpen
+                          ? i18n.translate('xpack.lens.formula.editorHelpInlineHideToolTip', {
+                              defaultMessage: 'Hide function reference',
+                            })
+                          : i18n.translate('xpack.lens.formula.editorHelpInlineShowToolTip', {
+                              defaultMessage: 'Show function reference',
+                            })
+                      }
+                      delay="long"
+                      position="top"
+                    >
+                      <EuiLink
+                        aria-label={i18n.translate('xpack.lens.formula.editorHelpInlineHideLabel', {
+                          defaultMessage: 'Hide function reference',
+                        })}
+                        className="lnsFormula__editorHelp lnsFormula__editorHelp--inline"
+                        color="text"
+                        onClick={() => setIsHelpOpen(!isHelpOpen)}
+                      >
+                        <EuiIcon type="help" />
+                        <EuiIcon type={isHelpOpen ? 'arrowDown' : 'arrowUp'} />
+                      </EuiLink>
+                    </EuiToolTip>
+                  ) : (
+                    <EuiToolTip
+                      content={i18n.translate('xpack.lens.formula.editorHelpOverlayToolTip', {
+                        defaultMessage: 'Function reference',
+                      })}
+                      position="top"
+                    >
+                      <EuiPopover
+                        panelClassName="lnsFormula__docs lnsFormula__docs--overlay"
+                        panelPaddingSize="none"
+                        anchorPosition="leftCenter"
+                        isOpen={isHelpOpen}
+                        closePopover={() => setIsHelpOpen(false)}
+                        ownFocus={false}
+                        button={
+                          <EuiButtonIcon
+                            className="lnsFormula__editorHelp lnsFormula__editorHelp--overlay"
+                            onClick={() => setIsHelpOpen(!isHelpOpen)}
+                            iconType="help"
+                            color="text"
+                            size="s"
+                            aria-label={i18n.translate(
+                              'xpack.lens.formula.editorHelpInlineShowToolTip',
+                              {
+                                defaultMessage: 'Show function reference',
+                              }
+                            )}
+                          />
+                        }
+                      >
+                        <MemoizedFormulaHelp
+                          isFullscreen={isFullscreen}
+                          indexPattern={indexPattern}
+                          operationDefinitionMap={visibleOperationsMap}
+                        />
+                      </EuiPopover>
+                    </EuiToolTip>
+                  )}
+                </EuiFlexItem>
+
+                {errorCount || warningCount ? (
+                  <EuiFlexItem className="lnsFormula__editorFooterGroup" grow={false}>
+                    <EuiPopover
+                      ownFocus={false}
+                      isOpen={isWarningOpen}
+                      closePopover={() => setIsWarningOpen(false)}
+                      button={
+                        <EuiButtonEmpty
+                          color={errorCount ? 'danger' : 'warning'}
+                          className="lnsFormula__editorError"
+                          iconType="alert"
+                          size="xs"
+                          flush="right"
+                          onClick={() => {
+                            setIsWarningOpen(!isWarningOpen);
+                          }}
+                        >
+                          {errorCount
+                            ? i18n.translate('xpack.lens.formulaErrorCount', {
+                                defaultMessage:
+                                  '{count} {count, plural, one {error} other {errors}}',
+                                values: { count: errorCount },
+                              })
+                            : null}
+                          {warningCount
+                            ? i18n.translate('xpack.lens.formulaWarningCount', {
+                                defaultMessage:
+                                  '{count} {count, plural, one {warning} other {warnings}}',
+                                values: { count: warningCount },
+                              })
+                            : null}
+                        </EuiButtonEmpty>
+                      }
+                    >
+                      {warnings.map(({ message, severity }, index) => (
+                        <div key={index} className="lnsFormula__warningText">
+                          <EuiText
+                            size="s"
+                            color={
+                              severity === monaco.MarkerSeverity.Warning ? 'warning' : 'danger'
+                            }
+                          >
+                            {message}
+                          </EuiText>
+                        </div>
+                      ))}
+                    </EuiPopover>
+                  </EuiFlexItem>
+                ) : null}
+              </EuiFlexGroup>
+            </div>
+          </div>
+
+          {isFullscreen && isHelpOpen ? (
+            <div className="lnsFormula__docs lnsFormula__docs--inline">
+              <MemoizedFormulaHelp
+                isFullscreen={isFullscreen}
+                indexPattern={indexPattern}
+                operationDefinitionMap={visibleOperationsMap}
+              />
+            </div>
+          ) : null}
+        </div>
+      </div>
+    </div>
+  );
+}
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx
new file mode 100644
index 0000000000000..afe5471666b22
--- /dev/null
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx
@@ -0,0 +1,469 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { useEffect, useRef, useState, useMemo } from 'react';
+import { i18n } from '@kbn/i18n';
+import {
+  EuiFlexGroup,
+  EuiFlexItem,
+  EuiLink,
+  EuiPopoverTitle,
+  EuiText,
+  EuiListGroupItem,
+  EuiListGroup,
+  EuiTitle,
+  EuiFieldSearch,
+  EuiHighlight,
+} from '@elastic/eui';
+import { Markdown } from '../../../../../../../../../src/plugins/kibana_react/public';
+import { IndexPattern } from '../../../../types';
+import { tinymathFunctions } from '../util';
+import { getPossibleFunctions } from './math_completion';
+import { hasFunctionFieldArgument } from '../validation';
+
+import type {
+  GenericOperationDefinition,
+  IndexPatternColumn,
+  OperationDefinition,
+  ParamEditorProps,
+} from '../../index';
+import type { FormulaIndexPatternColumn } from '../formula';
+
+function FormulaHelp({
+  indexPattern,
+  operationDefinitionMap,
+  isFullscreen,
+}: {
+  indexPattern: IndexPattern;
+  operationDefinitionMap: Record<string, GenericOperationDefinition>;
+  isFullscreen: boolean;
+}) {
+  const [selectedFunction, setSelectedFunction] = useState<string | undefined>();
+  const scrollTargets = useRef<Record<string, HTMLElement>>({});
+
+  useEffect(() => {
+    if (selectedFunction && scrollTargets.current[selectedFunction]) {
+      scrollTargets.current[selectedFunction].scrollIntoView();
+    }
+  }, [selectedFunction]);
+
+  const helpGroups: Array<{
+    label: string;
+    description?: string;
+    items: Array<{ label: string; description?: JSX.Element }>;
+  }> = [];
+
+  helpGroups.push({
+    label: i18n.translate('xpack.lens.formulaDocumentationHeading', {
+      defaultMessage: 'How it works',
+    }),
+    items: [],
+  });
+
+  helpGroups.push({
+    label: i18n.translate('xpack.lens.formulaDocumentation.elasticsearchSection', {
+      defaultMessage: 'Elasticsearch',
+    }),
+    description: i18n.translate('xpack.lens.formulaDocumentation.elasticsearchSectionDescription', {
+      defaultMessage:
+        'These functions will be executed on the raw documents for each row of the resulting table, aggregating all documents matching the break down dimensions into a single value.',
+    }),
+    items: [],
+  });
+
+  const availableFunctions = getPossibleFunctions(indexPattern);
+
+  // Es aggs
+  helpGroups[1].items.push(
+    ...availableFunctions
+      .filter(
+        (key) =>
+          key in operationDefinitionMap &&
+          operationDefinitionMap[key].documentation?.section === 'elasticsearch'
+      )
+      .sort()
+      .map((key) => ({
+        label: key,
+        description: (
+          <>
+            <h3>
+              {key}({operationDefinitionMap[key].documentation?.signature})
+            </h3>
+
+            {operationDefinitionMap[key].documentation?.description ? (
+              <Markdown markdown={operationDefinitionMap[key].documentation!.description} />
+            ) : null}
+          </>
+        ),
+      }))
+  );
+
+  helpGroups.push({
+    label: i18n.translate('xpack.lens.formulaDocumentation.columnCalculationSection', {
+      defaultMessage: 'Column-wise calculation',
+    }),
+    description: i18n.translate(
+      'xpack.lens.formulaDocumentation.columnCalculationSectionDescription',
+      {
+        defaultMessage:
+          'These functions will be executed for reach row of the resulting table, using data from cells from other rows as well as the current value.',
+      }
+    ),
+    items: [],
+  });
+
+  // Calculations aggs
+  helpGroups[2].items.push(
+    ...availableFunctions
+      .filter(
+        (key) =>
+          key in operationDefinitionMap &&
+          operationDefinitionMap[key].documentation?.section === 'calculation'
+      )
+      .sort()
+      .map((key) => ({
+        label: key,
+        description: (
+          <>
+            <h3>
+              {key}({operationDefinitionMap[key].documentation?.signature})
+            </h3>
+
+            {operationDefinitionMap[key].documentation?.description ? (
+              <Markdown markdown={operationDefinitionMap[key].documentation!.description} />
+            ) : null}
+          </>
+        ),
+        checked:
+          selectedFunction === `${key}: ${operationDefinitionMap[key].displayName}`
+            ? ('on' as const)
+            : undefined,
+      }))
+  );
+
+  helpGroups.push({
+    label: i18n.translate('xpack.lens.formulaDocumentation.mathSection', {
+      defaultMessage: 'Math',
+    }),
+    description: i18n.translate('xpack.lens.formulaDocumentation.mathSectionDescription', {
+      defaultMessage:
+        'These functions will be executed for reach row of the resulting table using single values from the same row calculated using other functions.',
+    }),
+    items: [],
+  });
+
+  const tinymathFns = useMemo(() => {
+    return getPossibleFunctions(indexPattern)
+      .filter((key) => key in tinymathFunctions)
+      .sort()
+      .map((key) => {
+        const [description, examples] = tinymathFunctions[key].help.split(`\`\`\``);
+        return {
+          label: key,
+          description: description.replace(/\n/g, '\n\n'),
+          examples: examples ? `\`\`\`${examples}\`\`\`` : '',
+        };
+      });
+  }, [indexPattern]);
+
+  helpGroups[3].items.push(
+    ...tinymathFns.map(({ label, description, examples }) => {
+      return {
+        label,
+        description: (
+          <>
+            <h3>{getFunctionSignatureLabel(label, operationDefinitionMap)}</h3>
+
+            <Markdown markdown={`${description}${examples}`} />
+          </>
+        ),
+      };
+    })
+  );
+
+  const [searchText, setSearchText] = useState('');
+
+  const normalizedSearchText = searchText.trim().toLocaleLowerCase();
+
+  const filteredHelpGroups = helpGroups
+    .map((group) => {
+      const items = group.items.filter((helpItem) => {
+        return (
+          !normalizedSearchText || helpItem.label.toLocaleLowerCase().includes(normalizedSearchText)
+        );
+      });
+      return { ...group, items };
+    })
+    .filter((group) => {
+      if (group.items.length > 0 || !normalizedSearchText) {
+        return true;
+      }
+      return group.label.toLocaleLowerCase().includes(normalizedSearchText);
+    });
+
+  return (
+    <>
+      <EuiPopoverTitle className="lnsFormula__docsHeader" paddingSize="s">
+        {i18n.translate('xpack.lens.formulaDocumentation.header', {
+          defaultMessage: 'Formula reference',
+        })}
+      </EuiPopoverTitle>
+
+      <EuiFlexGroup
+        className="lnsFormula__docsContent"
+        gutterSize="none"
+        responsive={false}
+        alignItems="stretch"
+      >
+        <EuiFlexItem className="lnsFormula__docsSidebar" grow={1}>
+          <EuiFlexGroup
+            className="lnsFormula__docsSidebarInner"
+            direction="column"
+            gutterSize="none"
+            responsive={false}
+          >
+            <EuiFlexItem className="lnsFormula__docsSearch" grow={false}>
+              <EuiFieldSearch
+                value={searchText}
+                onChange={(e) => {
+                  setSearchText(e.target.value);
+                }}
+                placeholder={i18n.translate('xpack.lens.formulaSearchPlaceholder', {
+                  defaultMessage: 'Search functions',
+                })}
+              />
+            </EuiFlexItem>
+
+            <EuiFlexItem className="lnsFormula__docsNav">
+              {filteredHelpGroups.map((helpGroup, index) => {
+                return (
+                  <nav className="lnsFormula__docsNavGroup" key={helpGroup.label}>
+                    <EuiTitle size="xxs">
+                      <h6>
+                        <EuiLink
+                          className="lnsFormula__docsNavGroupLink"
+                          color="text"
+                          onClick={() => {
+                            setSelectedFunction(helpGroup.label);
+                          }}
+                        >
+                          <EuiHighlight search={searchText}>{helpGroup.label}</EuiHighlight>
+                        </EuiLink>
+                      </h6>
+                    </EuiTitle>
+
+                    <EuiListGroup gutterSize="none">
+                      {helpGroup.items.map((helpItem) => {
+                        return (
+                          <EuiListGroupItem
+                            key={helpItem.label}
+                            label={
+                              <EuiHighlight search={searchText}>{helpItem.label}</EuiHighlight>
+                            }
+                            size="s"
+                            onClick={() => {
+                              setSelectedFunction(helpItem.label);
+                            }}
+                          />
+                        );
+                      })}
+                    </EuiListGroup>
+                  </nav>
+                );
+              })}
+            </EuiFlexItem>
+          </EuiFlexGroup>
+        </EuiFlexItem>
+
+        <EuiFlexItem className="lnsFormula__docsText" grow={2}>
+          <EuiText size="s">
+            <section
+              className="lnsFormula__docsTextIntro"
+              ref={(el) => {
+                if (el) {
+                  scrollTargets.current[helpGroups[0].label] = el;
+                }
+              }}
+            >
+              <Markdown
+                markdown={i18n.translate('xpack.lens.formulaDocumentation', {
+                  defaultMessage: `
+## How it works
+
+Lens formulas let you do math using a combination of Elasticsearch aggregations and
+math functions. There are three main types of functions:
+
+* Elasticsearch metrics, like \`sum(bytes)\`
+* Time series functions use Elasticsearch metrics as input, like \`cumulative_sum()\`
+* Math functions like \`round()\`
+
+An example formula that uses all of these:
+
+\`\`\`
+round(100 * moving_average(
+  average(cpu.load.pct),
+  window=10,
+  kql='datacenter.name: east*'
+))
+\`\`\`
+
+Elasticsearch functions take a field name, which can be in quotes. \`sum(bytes)\` is the same
+as \`sum("bytes")\`.
+
+Some functions take named arguments, like moving_average(count(), window=5)
+
+Elasticsearch metrics can be filtered using KQL or Lucene syntax. To add a filter, use the named
+parameter \`kql='field: value'\` or \`lucene=''\`. Always use single quotes when writing KQL or Lucene
+queries. If your search has a single quote in it, use a backslash to escape, like: \`kql='Women's'\'
+
+Math functions can take positional arguments, like pow(count(), 3) is the same as count() * count() * count()
+
+Use the symbols +, -, /, and * to perform basic math.
+                  `,
+                  description:
+                    'Text is in markdown. Do not translate function names or field names like sum(bytes)',
+                })}
+              />
+            </section>
+
+            {helpGroups.slice(1).map((helpGroup, index) => {
+              return (
+                <section
+                  className="lnsFormula__docsTextGroup"
+                  key={helpGroup.label}
+                  ref={(el) => {
+                    if (el) {
+                      scrollTargets.current[helpGroup.label] = el;
+                    }
+                  }}
+                >
+                  <h2>{helpGroup.label}</h2>
+
+                  <p>{helpGroup.description}</p>
+
+                  {helpGroups[index + 1].items.map((helpItem) => {
+                    return (
+                      <article
+                        className="lnsFormula__docsTextItem"
+                        key={helpItem.label}
+                        ref={(el) => {
+                          if (el) {
+                            scrollTargets.current[helpItem.label] = el;
+                          }
+                        }}
+                      >
+                        {helpItem.description}
+                      </article>
+                    );
+                  })}
+                </section>
+              );
+            })}
+          </EuiText>
+        </EuiFlexItem>
+      </EuiFlexGroup>
+    </>
+  );
+}
+
+export const MemoizedFormulaHelp = React.memo(FormulaHelp);
+
+export function getFunctionSignatureLabel(
+  name: string,
+  operationDefinitionMap: ParamEditorProps<FormulaIndexPatternColumn>['operationDefinitionMap'],
+  firstParam?: { label: string | [number, number] } | null
+): string {
+  if (tinymathFunctions[name]) {
+    return `${name}(${tinymathFunctions[name].positionalArguments
+      .map(({ name: argName, optional, type }) => `[${argName}]${optional ? '?' : ''}: ${type}`)
+      .join(', ')})`;
+  }
+  if (operationDefinitionMap[name]) {
+    const def = operationDefinitionMap[name];
+    let extraArgs = '';
+    if (def.filterable) {
+      extraArgs += hasFunctionFieldArgument(name) || 'operationParams' in def ? ',' : '';
+      extraArgs += i18n.translate('xpack.lens.formula.kqlExtraArguments', {
+        defaultMessage: '[kql]?: string, [lucene]?: string',
+      });
+    }
+    return `${name}(${def.documentation?.signature}${extraArgs})`;
+  }
+  return '';
+}
+
+function getFunctionArgumentsStringified(
+  params: Required<
+    OperationDefinition<IndexPatternColumn, 'field' | 'fullReference'>
+  >['operationParams']
+) {
+  return params
+    .map(
+      ({ name, type: argType, defaultValue = 5 }) =>
+        `${name}=${argType === 'string' ? `"${defaultValue}"` : defaultValue}`
+    )
+    .join(', ');
+}
+
+/**
+ * Get an array of strings containing all possible information about a specific
+ * operation type: examples and infos.
+ */
+export function getHelpTextContent(
+  type: string,
+  operationDefinitionMap: ParamEditorProps<FormulaIndexPatternColumn>['operationDefinitionMap']
+): { description: string; examples: string[] } {
+  const definition = operationDefinitionMap[type];
+  const description = definition.documentation?.description ?? '';
+
+  // as for the time being just add examples text.
+  // Later will enrich with more information taken from the operation definitions.
+  const examples: string[] = [];
+  // If the description already contain examples skip it
+  if (!/Example/.test(description)) {
+    if (!hasFunctionFieldArgument(type)) {
+      // ideally this should have the same example automation as the operations below
+      examples.push(`${type}()`);
+      return { description, examples };
+    }
+    if (definition.input === 'field') {
+      const mandatoryArgs = definition.operationParams?.filter(({ required }) => required) || [];
+      if (mandatoryArgs.length === 0) {
+        examples.push(`${type}(bytes)`);
+      }
+      if (mandatoryArgs.length) {
+        const additionalArgs = getFunctionArgumentsStringified(mandatoryArgs);
+        examples.push(`${type}(bytes, ${additionalArgs})`);
+      }
+      if (
+        definition.operationParams &&
+        mandatoryArgs.length !== definition.operationParams.length
+      ) {
+        const additionalArgs = getFunctionArgumentsStringified(definition.operationParams);
+        examples.push(`${type}(bytes, ${additionalArgs})`);
+      }
+    }
+    if (definition.input === 'fullReference') {
+      const mandatoryArgs = definition.operationParams?.filter(({ required }) => required) || [];
+      if (mandatoryArgs.length === 0) {
+        examples.push(`${type}(sum(bytes))`);
+      }
+      if (mandatoryArgs.length) {
+        const additionalArgs = getFunctionArgumentsStringified(mandatoryArgs);
+        examples.push(`${type}(sum(bytes), ${additionalArgs})`);
+      }
+      if (
+        definition.operationParams &&
+        mandatoryArgs.length !== definition.operationParams.length
+      ) {
+        const additionalArgs = getFunctionArgumentsStringified(definition.operationParams);
+        examples.push(`${type}(sum(bytes), ${additionalArgs})`);
+      }
+    }
+  }
+  return { description, examples };
+}
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/index.ts
new file mode 100644
index 0000000000000..4b6acefa6b30a
--- /dev/null
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/index.ts
@@ -0,0 +1,8 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export * from './formula_editor';
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_completion.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_completion.test.ts
new file mode 100644
index 0000000000000..9cd748f5759c9
--- /dev/null
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_completion.test.ts
@@ -0,0 +1,386 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { parse } from '@kbn/tinymath';
+import { monaco } from '@kbn/monaco';
+import { createMockedIndexPattern } from '../../../../mocks';
+import { GenericOperationDefinition } from '../../index';
+import type { IndexPatternField } from '../../../../types';
+import type { OperationMetadata } from '../../../../../types';
+import { dataPluginMock } from '../../../../../../../../../src/plugins/data/public/mocks';
+import { tinymathFunctions } from '../util';
+import {
+  getSignatureHelp,
+  getHover,
+  suggest,
+  monacoPositionToOffset,
+  getInfoAtZeroIndexedPosition,
+} from './math_completion';
+
+const buildGenericColumn = (type: string) => {
+  return ({ field }: { field?: IndexPatternField }) => {
+    return {
+      label: type,
+      dataType: 'number',
+      operationType: type,
+      sourceField: field?.name ?? undefined,
+      isBucketed: false,
+      scale: 'ratio',
+      timeScale: false,
+    };
+  };
+};
+
+const numericOperation = () => ({ dataType: 'number', isBucketed: false });
+const stringOperation = () => ({ dataType: 'string', isBucketed: true });
+
+// Only one of each type is needed
+const operationDefinitionMap: Record<string, GenericOperationDefinition> = {
+  sum: ({
+    type: 'sum',
+    input: 'field',
+    buildColumn: buildGenericColumn('sum'),
+    getPossibleOperationForField: (field: IndexPatternField) =>
+      field.type === 'number' ? numericOperation() : null,
+    documentation: {
+      section: 'elasticsearch',
+      signature: 'field: string',
+      description: 'description',
+    },
+  } as unknown) as GenericOperationDefinition,
+  count: ({
+    type: 'count',
+    input: 'field',
+    buildColumn: buildGenericColumn('count'),
+    getPossibleOperationForField: (field: IndexPatternField) =>
+      field.name === 'Records' ? numericOperation() : null,
+  } as unknown) as GenericOperationDefinition,
+  last_value: ({
+    type: 'last_value',
+    input: 'field',
+    buildColumn: buildGenericColumn('last_value'),
+    getPossibleOperationForField: (field: IndexPatternField) => ({
+      dataType: field.type,
+      isBucketed: false,
+    }),
+  } as unknown) as GenericOperationDefinition,
+  moving_average: ({
+    type: 'moving_average',
+    input: 'fullReference',
+    requiredReferences: [
+      {
+        input: ['field', 'managedReference'],
+        validateMetadata: (meta: OperationMetadata) =>
+          meta.dataType === 'number' && !meta.isBucketed,
+      },
+    ],
+    operationParams: [{ name: 'window', type: 'number', required: true }],
+    buildColumn: buildGenericColumn('moving_average'),
+    getPossibleOperation: numericOperation,
+  } as unknown) as GenericOperationDefinition,
+  cumulative_sum: ({
+    type: 'cumulative_sum',
+    input: 'fullReference',
+    buildColumn: buildGenericColumn('cumulative_sum'),
+    getPossibleOperation: numericOperation,
+  } as unknown) as GenericOperationDefinition,
+  terms: ({
+    type: 'terms',
+    input: 'field',
+    getPossibleOperationForField: stringOperation,
+  } as unknown) as GenericOperationDefinition,
+};
+
+describe('math completion', () => {
+  describe('signature help', () => {
+    function unwrapSignatures(signatureResult: monaco.languages.SignatureHelpResult) {
+      return signatureResult.value.signatures[0];
+    }
+
+    it('should silently handle parse errors', () => {
+      expect(unwrapSignatures(getSignatureHelp('sum(', 4, operationDefinitionMap))).toBeUndefined();
+    });
+
+    it('should return a signature for a field-based ES function', () => {
+      expect(unwrapSignatures(getSignatureHelp('sum()', 4, operationDefinitionMap))).toEqual({
+        label: 'sum(field: string)',
+        documentation: { value: 'description' },
+        parameters: [{ label: 'field' }],
+      });
+    });
+
+    it('should return a signature for count', () => {
+      expect(unwrapSignatures(getSignatureHelp('count()', 6, operationDefinitionMap))).toEqual({
+        label: 'count(undefined)',
+        documentation: { value: '' },
+        parameters: [],
+      });
+    });
+
+    it('should return a signature for a function with named parameters', () => {
+      expect(
+        unwrapSignatures(
+          getSignatureHelp('2 * moving_average(count(), window=)', 35, operationDefinitionMap)
+        )
+      ).toEqual({
+        label: expect.stringContaining('moving_average('),
+        documentation: { value: '' },
+        parameters: [
+          { label: 'function' },
+          {
+            label: 'window=number',
+            documentation: 'Required',
+          },
+        ],
+      });
+    });
+
+    it('should return a signature for an inner function', () => {
+      expect(
+        unwrapSignatures(
+          getSignatureHelp('2 * moving_average(count())', 25, operationDefinitionMap)
+        )
+      ).toEqual({
+        label: expect.stringContaining('count('),
+        parameters: [],
+        documentation: { value: '' },
+      });
+    });
+
+    it('should return a signature for a complex tinymath function', () => {
+      // 15 is the whitespace between the two arguments
+      expect(
+        unwrapSignatures(getSignatureHelp('clamp(count(), 5)', 15, operationDefinitionMap))
+      ).toEqual({
+        label: expect.stringContaining('clamp('),
+        documentation: { value: '' },
+        parameters: [
+          { label: 'value', documentation: '' },
+          { label: 'min', documentation: '' },
+          { label: 'max', documentation: '' },
+        ],
+      });
+    });
+  });
+
+  describe('hover provider', () => {
+    it('should silently handle parse errors', () => {
+      expect(getHover('sum(', 2, operationDefinitionMap)).toEqual({ contents: [] });
+    });
+
+    it('should show signature for a field-based ES function', () => {
+      expect(getHover('sum()', 2, operationDefinitionMap)).toEqual({
+        contents: [{ value: 'sum(field: string)' }],
+      });
+    });
+
+    it('should show signature for count', () => {
+      expect(getHover('count()', 2, operationDefinitionMap)).toEqual({
+        contents: [{ value: expect.stringContaining('count(') }],
+      });
+    });
+
+    it('should show signature for a function with named parameters', () => {
+      expect(getHover('2 * moving_average(count())', 10, operationDefinitionMap)).toEqual({
+        contents: [{ value: expect.stringContaining('moving_average(') }],
+      });
+    });
+
+    it('should show signature for an inner function', () => {
+      expect(getHover('2 * moving_average(count())', 22, operationDefinitionMap)).toEqual({
+        contents: [{ value: expect.stringContaining('count(') }],
+      });
+    });
+
+    it('should show signature for a complex tinymath function', () => {
+      expect(getHover('clamp(count(), 5)', 2, operationDefinitionMap)).toEqual({
+        contents: [{ value: expect.stringContaining('clamp([value]: number') }],
+      });
+    });
+  });
+
+  describe('autocomplete', () => {
+    it('should list all valid functions at the top level (fake test)', async () => {
+      // This test forces an invalid scenario, since the autocomplete actually requires
+      // some typing
+      const results = await suggest({
+        expression: '',
+        zeroIndexedOffset: 1,
+        context: {
+          triggerKind: monaco.languages.CompletionTriggerKind.TriggerCharacter,
+          triggerCharacter: '',
+        },
+        indexPattern: createMockedIndexPattern(),
+        operationDefinitionMap,
+        data: dataPluginMock.createStartContract(),
+      });
+      expect(results.list).toHaveLength(4 + Object.keys(tinymathFunctions).length);
+      ['sum', 'moving_average', 'cumulative_sum', 'last_value'].forEach((key) => {
+        expect(results.list).toEqual(expect.arrayContaining([{ label: key, type: 'operation' }]));
+      });
+      Object.keys(tinymathFunctions).forEach((key) => {
+        expect(results.list).toEqual(expect.arrayContaining([{ label: key, type: 'operation' }]));
+      });
+    });
+
+    it('should list all valid sub-functions for a fullReference', async () => {
+      const results = await suggest({
+        expression: 'moving_average()',
+        zeroIndexedOffset: 15,
+        context: {
+          triggerKind: monaco.languages.CompletionTriggerKind.TriggerCharacter,
+          triggerCharacter: '(',
+        },
+        indexPattern: createMockedIndexPattern(),
+        operationDefinitionMap,
+        data: dataPluginMock.createStartContract(),
+      });
+      expect(results.list).toHaveLength(2);
+      ['sum', 'last_value'].forEach((key) => {
+        expect(results.list).toEqual(expect.arrayContaining([{ label: key, type: 'operation' }]));
+      });
+    });
+
+    it('should list all valid named arguments for a fullReference', async () => {
+      const results = await suggest({
+        expression: 'moving_average(count(),)',
+        zeroIndexedOffset: 23,
+        context: {
+          triggerKind: monaco.languages.CompletionTriggerKind.TriggerCharacter,
+          triggerCharacter: ',',
+        },
+        indexPattern: createMockedIndexPattern(),
+        operationDefinitionMap,
+        data: dataPluginMock.createStartContract(),
+      });
+      expect(results.list).toEqual(['window']);
+    });
+
+    it('should not list named arguments when they are already in use', async () => {
+      const results = await suggest({
+        expression: 'moving_average(count(), window=5, )',
+        zeroIndexedOffset: 34,
+        context: {
+          triggerKind: monaco.languages.CompletionTriggerKind.TriggerCharacter,
+          triggerCharacter: ',',
+        },
+        indexPattern: createMockedIndexPattern(),
+        operationDefinitionMap,
+        data: dataPluginMock.createStartContract(),
+      });
+      expect(results.list).toEqual([]);
+    });
+
+    it('should list all valid positional arguments for a tinymath function used by name', async () => {
+      const results = await suggest({
+        expression: 'divide(count(), )',
+        zeroIndexedOffset: 16,
+        context: {
+          triggerKind: monaco.languages.CompletionTriggerKind.TriggerCharacter,
+          triggerCharacter: ',',
+        },
+        indexPattern: createMockedIndexPattern(),
+        operationDefinitionMap,
+        data: dataPluginMock.createStartContract(),
+      });
+      expect(results.list).toHaveLength(4 + Object.keys(tinymathFunctions).length);
+      ['sum', 'moving_average', 'cumulative_sum', 'last_value'].forEach((key) => {
+        expect(results.list).toEqual(expect.arrayContaining([{ label: key, type: 'math' }]));
+      });
+      Object.keys(tinymathFunctions).forEach((key) => {
+        expect(results.list).toEqual(expect.arrayContaining([{ label: key, type: 'math' }]));
+      });
+    });
+
+    it('should list all valid positional arguments for a tinymath function used with alias', async () => {
+      const results = await suggest({
+        expression: 'count() / ',
+        zeroIndexedOffset: 10,
+        context: {
+          triggerKind: monaco.languages.CompletionTriggerKind.TriggerCharacter,
+          triggerCharacter: ',',
+        },
+        indexPattern: createMockedIndexPattern(),
+        operationDefinitionMap,
+        data: dataPluginMock.createStartContract(),
+      });
+      expect(results.list).toHaveLength(4 + Object.keys(tinymathFunctions).length);
+      ['sum', 'moving_average', 'cumulative_sum', 'last_value'].forEach((key) => {
+        expect(results.list).toEqual(expect.arrayContaining([{ label: key, type: 'math' }]));
+      });
+      Object.keys(tinymathFunctions).forEach((key) => {
+        expect(results.list).toEqual(expect.arrayContaining([{ label: key, type: 'math' }]));
+      });
+    });
+
+    it('should not autocomplete any fields for the count function', async () => {
+      const results = await suggest({
+        expression: 'count()',
+        zeroIndexedOffset: 6,
+        context: {
+          triggerKind: monaco.languages.CompletionTriggerKind.TriggerCharacter,
+          triggerCharacter: '(',
+        },
+        indexPattern: createMockedIndexPattern(),
+        operationDefinitionMap,
+        data: dataPluginMock.createStartContract(),
+      });
+      expect(results.list).toHaveLength(0);
+    });
+
+    it('should autocomplete and validate the right type of field', async () => {
+      const results = await suggest({
+        expression: 'sum()',
+        zeroIndexedOffset: 4,
+        context: {
+          triggerKind: monaco.languages.CompletionTriggerKind.TriggerCharacter,
+          triggerCharacter: '(',
+        },
+        indexPattern: createMockedIndexPattern(),
+        operationDefinitionMap,
+        data: dataPluginMock.createStartContract(),
+      });
+      expect(results.list).toEqual(['bytes', 'memory']);
+    });
+
+    it('should autocomplete only operations that provide numeric output', async () => {
+      const results = await suggest({
+        expression: 'last_value()',
+        zeroIndexedOffset: 11,
+        context: {
+          triggerKind: monaco.languages.CompletionTriggerKind.TriggerCharacter,
+          triggerCharacter: '(',
+        },
+        indexPattern: createMockedIndexPattern(),
+        operationDefinitionMap,
+        data: dataPluginMock.createStartContract(),
+      });
+      expect(results.list).toEqual(['bytes', 'memory']);
+    });
+  });
+
+  describe('monacoPositionToOffset', () => {
+    it('should work with multi-line strings accounting for newline characters', () => {
+      const input = `012
+456
+89')`;
+      expect(input[monacoPositionToOffset(input, new monaco.Position(1, 1))]).toEqual('0');
+      expect(input[monacoPositionToOffset(input, new monaco.Position(3, 2))]).toEqual('9');
+    });
+  });
+
+  describe('getInfoAtZeroIndexedPosition', () => {
+    it('should return the location for a function inside multiple levels of math', () => {
+      const expression = `count() + 5 + average(LENS_MATH_MARKER)`;
+      const ast = parse(expression);
+      expect(getInfoAtZeroIndexedPosition(ast, 22)).toEqual({
+        ast: expect.objectContaining({ value: 'LENS_MATH_MARKER' }),
+        parent: expect.objectContaining({ name: 'average' }),
+      });
+    });
+  });
+});
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_completion.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_completion.ts
new file mode 100644
index 0000000000000..df747e532b38a
--- /dev/null
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_completion.ts
@@ -0,0 +1,594 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { uniq, startsWith } from 'lodash';
+import { i18n } from '@kbn/i18n';
+import { monaco } from '@kbn/monaco';
+import {
+  parse,
+  TinymathLocation,
+  TinymathAST,
+  TinymathFunction,
+  TinymathNamedArgument,
+} from '@kbn/tinymath';
+import type {
+  DataPublicPluginStart,
+  QuerySuggestion,
+} from '../../../../../../../../../src/plugins/data/public';
+import { IndexPattern } from '../../../../types';
+import { memoizedGetAvailableOperationsByMetadata } from '../../../operations';
+import { tinymathFunctions, groupArgsByType } from '../util';
+import type { GenericOperationDefinition } from '../..';
+import { getFunctionSignatureLabel, getHelpTextContent } from './formula_help';
+import { hasFunctionFieldArgument } from '../validation';
+
+export enum SUGGESTION_TYPE {
+  FIELD = 'field',
+  NAMED_ARGUMENT = 'named_argument',
+  FUNCTIONS = 'functions',
+  KQL = 'kql',
+}
+
+export type LensMathSuggestion =
+  | string
+  | {
+      label: string;
+      type: 'operation' | 'math';
+    }
+  | QuerySuggestion;
+
+export interface LensMathSuggestions {
+  list: LensMathSuggestion[];
+  type: SUGGESTION_TYPE;
+}
+
+function inLocation(cursorPosition: number, location: TinymathLocation) {
+  return cursorPosition >= location.min && cursorPosition < location.max;
+}
+
+const MARKER = 'LENS_MATH_MARKER';
+
+export function getInfoAtZeroIndexedPosition(
+  ast: TinymathAST,
+  zeroIndexedPosition: number,
+  parent?: TinymathFunction
+): undefined | { ast: TinymathAST; parent?: TinymathFunction } {
+  if (typeof ast === 'number') {
+    return;
+  }
+  // +, -, *, and / do not have location any more
+  if (ast.location && !inLocation(zeroIndexedPosition, ast.location)) {
+    return;
+  }
+  if (ast.type === 'function') {
+    const [match] = ast.args
+      .map((arg) => getInfoAtZeroIndexedPosition(arg, zeroIndexedPosition, ast))
+      .filter((a) => a);
+    if (match) {
+      return match;
+    } else if (ast.location) {
+      return { ast };
+    } else {
+      // None of the arguments match, but we don't know the position so it's not a match
+      return;
+    }
+  }
+  return {
+    ast,
+    parent,
+  };
+}
+
+export function offsetToRowColumn(expression: string, offset: number): monaco.Position {
+  const lines = expression.split(/\n/);
+  let remainingChars = offset;
+  let lineNumber = 1;
+  for (const line of lines) {
+    if (line.length >= remainingChars) {
+      return new monaco.Position(lineNumber, remainingChars);
+    }
+    remainingChars -= line.length + 1;
+    lineNumber++;
+  }
+
+  throw new Error('Algorithm failure');
+}
+
+export function monacoPositionToOffset(expression: string, position: monaco.Position): number {
+  const lines = expression.split(/\n/);
+  return lines
+    .slice(0, position.lineNumber)
+    .reduce(
+      (prev, current, index) =>
+        prev + (index === position.lineNumber - 1 ? position.column - 1 : current.length + 1),
+      0
+    );
+}
+
+export async function suggest({
+  expression,
+  zeroIndexedOffset,
+  context,
+  indexPattern,
+  operationDefinitionMap,
+  data,
+}: {
+  expression: string;
+  zeroIndexedOffset: number;
+  context: monaco.languages.CompletionContext;
+  indexPattern: IndexPattern;
+  operationDefinitionMap: Record<string, GenericOperationDefinition>;
+  data: DataPublicPluginStart;
+}): Promise<{ list: LensMathSuggestion[]; type: SUGGESTION_TYPE }> {
+  const text =
+    expression.substr(0, zeroIndexedOffset) + MARKER + expression.substr(zeroIndexedOffset);
+  try {
+    const ast = parse(text);
+
+    const tokenInfo = getInfoAtZeroIndexedPosition(ast, zeroIndexedOffset);
+    const tokenAst = tokenInfo?.ast;
+
+    const isNamedArgument =
+      tokenInfo?.parent &&
+      typeof tokenAst !== 'number' &&
+      tokenAst &&
+      'type' in tokenAst &&
+      tokenAst.type === 'namedArgument';
+    if (tokenInfo?.parent && (context.triggerCharacter === '=' || isNamedArgument)) {
+      return await getNamedArgumentSuggestions({
+        ast: tokenAst as TinymathNamedArgument,
+        data,
+        indexPattern,
+      });
+    } else if (tokenInfo?.parent) {
+      return getArgumentSuggestions(
+        tokenInfo.parent,
+        tokenInfo.parent.args.findIndex((a) => a === tokenAst),
+        indexPattern,
+        operationDefinitionMap
+      );
+    }
+    if (
+      typeof tokenAst === 'object' &&
+      Boolean(tokenAst.type === 'variable' || tokenAst.type === 'function')
+    ) {
+      const nameWithMarker = tokenAst.type === 'function' ? tokenAst.name : tokenAst.value;
+      return getFunctionSuggestions(
+        nameWithMarker.split(MARKER)[0],
+        indexPattern,
+        operationDefinitionMap
+      );
+    }
+  } catch (e) {
+    // Fail silently
+  }
+  return { list: [], type: SUGGESTION_TYPE.FIELD };
+}
+
+export function getPossibleFunctions(
+  indexPattern: IndexPattern,
+  operationDefinitionMap?: Record<string, GenericOperationDefinition>
+) {
+  const available = memoizedGetAvailableOperationsByMetadata(indexPattern, operationDefinitionMap);
+  const possibleOperationNames: string[] = [];
+  available.forEach((a) => {
+    if (a.operationMetaData.dataType === 'number' && !a.operationMetaData.isBucketed) {
+      possibleOperationNames.push(
+        ...a.operations.filter((o) => o.type !== 'managedReference').map((o) => o.operationType)
+      );
+    }
+  });
+
+  return [...uniq(possibleOperationNames), ...Object.keys(tinymathFunctions)];
+}
+
+function getFunctionSuggestions(
+  prefix: string,
+  indexPattern: IndexPattern,
+  operationDefinitionMap: Record<string, GenericOperationDefinition>
+) {
+  return {
+    list: uniq(
+      getPossibleFunctions(indexPattern, operationDefinitionMap).filter((func) =>
+        startsWith(func, prefix)
+      )
+    ).map((func) => ({ label: func, type: 'operation' as const })),
+    type: SUGGESTION_TYPE.FUNCTIONS,
+  };
+}
+
+function getArgumentSuggestions(
+  ast: TinymathFunction,
+  position: number,
+  indexPattern: IndexPattern,
+  operationDefinitionMap: Record<string, GenericOperationDefinition>
+) {
+  const { name } = ast;
+  const operation = operationDefinitionMap[name];
+  if (!operation && !tinymathFunctions[name]) {
+    return { list: [], type: SUGGESTION_TYPE.FIELD };
+  }
+
+  const tinymathFunction = tinymathFunctions[name];
+  if (tinymathFunction) {
+    if (tinymathFunction.positionalArguments[position]) {
+      return {
+        list: uniq(getPossibleFunctions(indexPattern, operationDefinitionMap)).map((f) => ({
+          type: 'math' as const,
+          label: f,
+        })),
+        type: SUGGESTION_TYPE.FUNCTIONS,
+      };
+    }
+    return { list: [], type: SUGGESTION_TYPE.FIELD };
+  }
+
+  if (position > 0 || !hasFunctionFieldArgument(operation.type)) {
+    const { namedArguments } = groupArgsByType(ast.args);
+    const list = [];
+    if (operation.filterable) {
+      if (!namedArguments.find((arg) => arg.name === 'kql')) {
+        list.push('kql');
+      }
+      if (!namedArguments.find((arg) => arg.name === 'lucene')) {
+        list.push('lucene');
+      }
+    }
+    if ('operationParams' in operation) {
+      // Exclude any previously used named args
+      list.push(
+        ...operation
+          .operationParams!.filter(
+            (param) =>
+              // Keep the param if it's the first use
+              !namedArguments.find((arg) => arg.name === param.name)
+          )
+          .map((p) => p.name)
+      );
+    }
+    return { list, type: SUGGESTION_TYPE.NAMED_ARGUMENT };
+  }
+
+  if (operation.input === 'field' && position === 0) {
+    const available = memoizedGetAvailableOperationsByMetadata(
+      indexPattern,
+      operationDefinitionMap
+    );
+    // TODO: This only allow numeric functions, will reject last_value(string) for example.
+    const validOperation = available.find(
+      ({ operationMetaData }) =>
+        operationMetaData.dataType === 'number' && !operationMetaData.isBucketed
+    );
+    if (validOperation) {
+      const fields = validOperation.operations
+        .filter((op) => op.operationType === operation.type)
+        .map((op) => ('field' in op ? op.field : undefined))
+        .filter((field) => field);
+      return { list: fields as string[], type: SUGGESTION_TYPE.FIELD };
+    } else {
+      return { list: [], type: SUGGESTION_TYPE.FIELD };
+    }
+  }
+
+  if (operation.input === 'fullReference') {
+    const available = memoizedGetAvailableOperationsByMetadata(
+      indexPattern,
+      operationDefinitionMap
+    );
+    const possibleOperationNames: string[] = [];
+    available.forEach((a) => {
+      if (
+        operation.requiredReferences.some((requirement) =>
+          requirement.validateMetadata(a.operationMetaData)
+        )
+      ) {
+        possibleOperationNames.push(
+          ...a.operations
+            .filter((o) =>
+              operation.requiredReferences.some((requirement) => requirement.input.includes(o.type))
+            )
+            .map((o) => o.operationType)
+        );
+      }
+    });
+    return {
+      list: uniq(possibleOperationNames).map((n) => ({ label: n, type: 'operation' as const })),
+      type: SUGGESTION_TYPE.FUNCTIONS,
+    };
+  }
+
+  return { list: [], type: SUGGESTION_TYPE.FIELD };
+}
+
+export async function getNamedArgumentSuggestions({
+  ast,
+  data,
+  indexPattern,
+}: {
+  ast: TinymathNamedArgument;
+  indexPattern: IndexPattern;
+  data: DataPublicPluginStart;
+}) {
+  if (ast.name !== 'kql' && ast.name !== 'lucene') {
+    return { list: [], type: SUGGESTION_TYPE.KQL };
+  }
+  if (!data.autocomplete.hasQuerySuggestions(ast.name === 'kql' ? 'kuery' : 'lucene')) {
+    return { list: [], type: SUGGESTION_TYPE.KQL };
+  }
+
+  const query = ast.value.split(MARKER)[0];
+  const position = ast.value.indexOf(MARKER) + 1;
+
+  const suggestions = await data.autocomplete.getQuerySuggestions({
+    language: ast.name === 'kql' ? 'kuery' : 'lucene',
+    query,
+    selectionStart: position,
+    selectionEnd: position,
+    indexPatterns: [indexPattern],
+    boolFilter: [],
+  });
+  return {
+    list: suggestions ?? [],
+    type: SUGGESTION_TYPE.KQL,
+  };
+}
+
+const TRIGGER_SUGGESTION_COMMAND = {
+  title: 'Trigger Suggestion Dialog',
+  id: 'editor.action.triggerSuggest',
+};
+
+export function getSuggestion(
+  suggestion: LensMathSuggestion,
+  type: SUGGESTION_TYPE,
+  operationDefinitionMap: Record<string, GenericOperationDefinition>,
+  triggerChar: string | undefined
+): monaco.languages.CompletionItem {
+  let kind: monaco.languages.CompletionItemKind = monaco.languages.CompletionItemKind.Method;
+  let label: string =
+    typeof suggestion === 'string'
+      ? suggestion
+      : 'label' in suggestion
+      ? suggestion.label
+      : suggestion.text;
+  let insertText: string | undefined;
+  let insertTextRules: monaco.languages.CompletionItem['insertTextRules'];
+  let detail: string = '';
+  let command: monaco.languages.CompletionItem['command'];
+  let sortText: string = '';
+  const filterText: string = label;
+
+  switch (type) {
+    case SUGGESTION_TYPE.FIELD:
+      kind = monaco.languages.CompletionItemKind.Value;
+      break;
+    case SUGGESTION_TYPE.FUNCTIONS:
+      insertText = `${label}($0)`;
+      insertTextRules = monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet;
+      if (typeof suggestion !== 'string') {
+        if ('text' in suggestion) break;
+        label = getFunctionSignatureLabel(suggestion.label, operationDefinitionMap);
+        const tinymathFunction = tinymathFunctions[suggestion.label];
+        if (tinymathFunction) {
+          detail = 'TinyMath';
+          kind = monaco.languages.CompletionItemKind.Method;
+        } else {
+          kind = monaco.languages.CompletionItemKind.Constant;
+          detail = 'Elasticsearch';
+          // Always put ES functions first
+          sortText = `0${label}`;
+          command = TRIGGER_SUGGESTION_COMMAND;
+        }
+      }
+      break;
+    case SUGGESTION_TYPE.NAMED_ARGUMENT:
+      kind = monaco.languages.CompletionItemKind.Keyword;
+      if (label === 'kql' || label === 'lucene') {
+        command = TRIGGER_SUGGESTION_COMMAND;
+        insertText = `${label}='$0'`;
+        insertTextRules = monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet;
+        sortText = `zzz${label}`;
+      }
+      label = `${label}=`;
+      detail = '';
+      break;
+    case SUGGESTION_TYPE.KQL:
+      if (triggerChar === ':') {
+        insertText = `${triggerChar} ${label}`;
+      } else {
+        // concatenate KQL suggestion for faster query composition
+        command = TRIGGER_SUGGESTION_COMMAND;
+      }
+      if (label.includes(`'`)) {
+        insertText = (insertText || label).replaceAll(`'`, "\\'");
+      }
+      break;
+  }
+
+  return {
+    detail,
+    kind,
+    label,
+    insertText: insertText ?? label,
+    insertTextRules,
+    command,
+    additionalTextEdits: [],
+    // @ts-expect-error Monaco says this type is required, but provides a default value
+    range: undefined,
+    sortText,
+    filterText,
+  };
+}
+
+function getOperationTypeHelp(
+  name: string,
+  operationDefinitionMap: Record<string, GenericOperationDefinition>
+) {
+  const { description: descriptionInMarkdown, examples } = getHelpTextContent(
+    name,
+    operationDefinitionMap
+  );
+  const examplesInMarkdown = examples.length
+    ? `\n\n**${i18n.translate('xpack.lens.formulaExampleMarkdown', {
+        defaultMessage: 'Examples',
+      })}**
+
+  ${examples.map((example) => `\`${example}\``).join('\n\n')}`
+    : '';
+  return {
+    value: `${descriptionInMarkdown}${examplesInMarkdown}`,
+  };
+}
+
+function getSignaturesForFunction(
+  name: string,
+  operationDefinitionMap: Record<string, GenericOperationDefinition>
+) {
+  if (tinymathFunctions[name]) {
+    const stringify = getFunctionSignatureLabel(name, operationDefinitionMap);
+    const documentation = tinymathFunctions[name].help.replace(/\n/g, '\n\n');
+    return [
+      {
+        label: stringify,
+        documentation: { value: documentation },
+        parameters: tinymathFunctions[name].positionalArguments.map((arg) => ({
+          label: arg.name,
+          documentation: arg.optional
+            ? i18n.translate('xpack.lens.formula.optionalArgument', {
+                defaultMessage: 'Optional. Default value is {defaultValue}',
+                values: {
+                  defaultValue: arg.defaultValue,
+                },
+              })
+            : '',
+        })),
+      },
+    ];
+  }
+  if (operationDefinitionMap[name]) {
+    const def = operationDefinitionMap[name];
+
+    const firstParam: monaco.languages.ParameterInformation | null = hasFunctionFieldArgument(name)
+      ? {
+          label: def.input === 'field' ? 'field' : def.input === 'fullReference' ? 'function' : '',
+        }
+      : null;
+
+    const functionLabel = getFunctionSignatureLabel(name, operationDefinitionMap, firstParam);
+    const documentation = getOperationTypeHelp(name, operationDefinitionMap);
+    if ('operationParams' in def && def.operationParams) {
+      return [
+        {
+          label: functionLabel,
+          parameters: [
+            ...(firstParam ? [firstParam] : []),
+            ...def.operationParams.map((arg) => ({
+              label: `${arg.name}=${arg.type}`,
+              documentation: arg.required
+                ? i18n.translate('xpack.lens.formula.requiredArgument', {
+                    defaultMessage: 'Required',
+                  })
+                : '',
+            })),
+          ],
+          documentation,
+        },
+      ];
+    }
+    return [
+      {
+        label: functionLabel,
+        parameters: firstParam ? [firstParam] : [],
+        documentation,
+      },
+    ];
+  }
+  return [];
+}
+
+export function getSignatureHelp(
+  expression: string,
+  position: number,
+  operationDefinitionMap: Record<string, GenericOperationDefinition>
+): monaco.languages.SignatureHelpResult {
+  const text = expression.substr(0, position) + MARKER + expression.substr(position);
+  try {
+    const ast = parse(text);
+
+    const tokenInfo = getInfoAtZeroIndexedPosition(ast, position);
+
+    let signatures: ReturnType<typeof getSignaturesForFunction> = [];
+    let index = 0;
+    if (tokenInfo?.parent) {
+      const name = tokenInfo.parent.name;
+      // reference equality is fine here because of the way the getInfo function works
+      index = tokenInfo.parent.args.findIndex((arg) => arg === tokenInfo.ast);
+      signatures = getSignaturesForFunction(name, operationDefinitionMap);
+    } else if (typeof tokenInfo?.ast === 'object' && tokenInfo.ast.type === 'function') {
+      const name = tokenInfo.ast.name;
+      signatures = getSignaturesForFunction(name, operationDefinitionMap);
+    }
+    if (signatures.length) {
+      return {
+        value: {
+          // remove the documentation
+          signatures: signatures.map(({ documentation, ...signature }) => ({
+            ...signature,
+            // extract only the first section (usually few lines)
+            documentation: { value: documentation.value.split('\n\n')[0] },
+          })),
+          activeParameter: index,
+          activeSignature: 0,
+        },
+        dispose: () => {},
+      };
+    }
+  } catch (e) {
+    // do nothing
+  }
+  return { value: { signatures: [], activeParameter: 0, activeSignature: 0 }, dispose: () => {} };
+}
+
+export function getHover(
+  expression: string,
+  position: number,
+  operationDefinitionMap: Record<string, GenericOperationDefinition>
+): monaco.languages.Hover {
+  try {
+    const ast = parse(expression);
+
+    const tokenInfo = getInfoAtZeroIndexedPosition(ast, position);
+
+    if (!tokenInfo || typeof tokenInfo.ast === 'number' || !('name' in tokenInfo.ast)) {
+      return { contents: [] };
+    }
+
+    const name = tokenInfo.ast.name;
+    const signatures = getSignaturesForFunction(name, operationDefinitionMap);
+    if (signatures.length) {
+      const { label } = signatures[0];
+
+      return {
+        contents: [{ value: label }],
+      };
+    }
+  } catch (e) {
+    // do nothing
+  }
+  return { contents: [] };
+}
+
+export function getTokenInfo(expression: string, position: number) {
+  const text = expression.substr(0, position) + MARKER + expression.substr(position);
+  try {
+    const ast = parse(text);
+
+    return getInfoAtZeroIndexedPosition(ast, position);
+  } catch (e) {
+    return;
+  }
+}
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_tokenization.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_tokenization.tsx
new file mode 100644
index 0000000000000..17394560f8031
--- /dev/null
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_tokenization.tsx
@@ -0,0 +1,66 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { monaco } from '@kbn/monaco';
+
+export const LANGUAGE_ID = 'lens_math';
+monaco.languages.register({ id: LANGUAGE_ID });
+
+export const languageConfiguration: monaco.languages.LanguageConfiguration = {
+  wordPattern: /[^()'"\s]+/g,
+  brackets: [['(', ')']],
+  autoClosingPairs: [
+    { open: '(', close: ')' },
+    { open: `'`, close: `'` },
+    { open: '"', close: '"' },
+  ],
+  surroundingPairs: [
+    { open: '(', close: ')' },
+    { open: `'`, close: `'` },
+    { open: '"', close: '"' },
+  ],
+};
+
+export const lexerRules = {
+  defaultToken: 'invalid',
+  tokenPostfix: '',
+  ignoreCase: true,
+  brackets: [{ open: '(', close: ')', token: 'delimiter.parenthesis' }],
+  escapes: /\\(?:[\\"'])/,
+  tokenizer: {
+    root: [
+      [/\s+/, 'whitespace'],
+      [/-?(\d*\.)?\d+([eE][+\-]?\d+)?/, 'number'],
+      [/[a-zA-Z0-9][a-zA-Z0-9_\-\.]*/, 'keyword'],
+      [/[,=:]/, 'delimiter'],
+      // strings double quoted
+      [/"([^"\\]|\\.)*$/, 'string.invalid'], // string without termination
+      [/"/, 'string', '@string_dq'],
+      // strings single quoted
+      [/'([^'\\]|\\.)*$/, 'string.invalid'], // string without termination
+      [/'/, 'string', '@string_sq'],
+      [/\+|\-|\*|\//, 'keyword.operator'],
+      [/[\(]/, 'delimiter'],
+      [/[\)]/, 'delimiter'],
+    ],
+    string_dq: [
+      [/[^\\"]+/, 'string'],
+      [/@escapes/, 'string.escape'],
+      [/\\./, 'string.escape.invalid'],
+      [/"/, 'string', '@pop'],
+    ],
+    string_sq: [
+      [/[^\\']+/, 'string'],
+      [/@escapes/, 'string.escape'],
+      [/\\./, 'string.escape.invalid'],
+      [/'/, 'string', '@pop'],
+    ],
+  },
+} as monaco.languages.IMonarchLanguage;
+
+monaco.languages.setMonarchTokensProvider(LANGUAGE_ID, lexerRules);
+monaco.languages.setLanguageConfiguration(LANGUAGE_ID, languageConfiguration);
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx
index 4a511e14d59e0..e1c722fd9cb38 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx
@@ -14,8 +14,10 @@ import { tinymathFunctions } from './util';
 
 jest.mock('../../layer_helpers', () => {
   return {
-    getColumnOrder: ({ columns }: { columns: Record<string, IndexPatternColumn> }) =>
-      Object.keys(columns),
+    getColumnOrder: jest.fn(({ columns }: { columns: Record<string, IndexPatternColumn> }) =>
+      Object.keys(columns)
+    ),
+    getManagedColumnsFrom: jest.fn().mockReturnValue([]),
   };
 });
 
@@ -142,7 +144,7 @@ describe('formula', () => {
           indexPattern,
         })
       ).toEqual({
-        label: 'Formula',
+        label: 'average(bytes)',
         dataType: 'number',
         operationType: 'formula',
         isBucketed: false,
@@ -170,7 +172,7 @@ describe('formula', () => {
           indexPattern,
         })
       ).toEqual({
-        label: 'Formula',
+        label: 'average(bytes)',
         dataType: 'number',
         operationType: 'formula',
         isBucketed: false,
@@ -204,7 +206,7 @@ describe('formula', () => {
           indexPattern,
         })
       ).toEqual({
-        label: 'Formula',
+        label: `average(bytes, kql='category.keyword: "Men\\'s Clothing" or category.keyword: "Men\\'s Shoes"')`,
         dataType: 'number',
         operationType: 'formula',
         isBucketed: false,
@@ -233,7 +235,7 @@ describe('formula', () => {
           indexPattern,
         })
       ).toEqual({
-        label: 'Formula',
+        label: `count(lucene='*')`,
         dataType: 'number',
         operationType: 'formula',
         isBucketed: false,
@@ -291,7 +293,7 @@ describe('formula', () => {
           operationDefinitionMap
         )
       ).toEqual({
-        label: 'Formula',
+        label: 'moving_average(average(bytes), window=3)',
         dataType: 'number',
         operationType: 'formula',
         isBucketed: false,
@@ -375,6 +377,7 @@ describe('formula', () => {
           ...layer.columns,
           col1: {
             ...currentColumn,
+            label: formula,
             params: {
               ...currentColumn.params,
               formula,
@@ -415,6 +418,7 @@ describe('formula', () => {
           ...layer.columns,
           col1: {
             ...currentColumn,
+            label: 'average(bytes)',
             references: ['col1X1'],
             params: {
               ...currentColumn.params,
@@ -565,7 +569,7 @@ describe('formula', () => {
       ).toEqual({
         col1X0: { min: 15, max: 29 },
         col1X2: { min: 0, max: 41 },
-        col1X3: { min: 43, max: 50 },
+        col1X3: { min: 42, max: 50 },
       });
     });
   });
@@ -787,6 +791,34 @@ invalid: "
       }
     });
 
+    it('returns an error if formula or math operations are used', () => {
+      const formulaFormulas = ['formula()', 'formula(bytes)', 'formula(formula())'];
+
+      for (const formula of formulaFormulas) {
+        expect(
+          formulaOperation.getErrorMessage!(
+            getNewLayerWithFormula(formula),
+            'col1',
+            indexPattern,
+            operationDefinitionMap
+          )
+        ).toEqual(['Operation formula not found']);
+      }
+
+      const mathFormulas = ['math()', 'math(bytes)', 'math(math())'];
+
+      for (const formula of mathFormulas) {
+        expect(
+          formulaOperation.getErrorMessage!(
+            getNewLayerWithFormula(formula),
+            'col1',
+            indexPattern,
+            operationDefinitionMap
+          )
+        ).toEqual(['Operation math not found']);
+      }
+    });
+
     it('returns an error if field operation in formula have the wrong first argument', () => {
       const formulas = [
         'average(7)',
@@ -897,6 +929,150 @@ invalid: "
       ).toEqual(undefined);
     });
 
+    it('returns no error for a query edge case', () => {
+      const formulas = [
+        `count(kql='')`,
+        `count(lucene='')`,
+        `moving_average(count(kql=''), window=7)`,
+        `count(kql='bytes >= 4000')`,
+        `count(kql='bytes <= 4000')`,
+        `count(kql='bytes = 4000')`,
+      ];
+      for (const formula of formulas) {
+        expect(
+          formulaOperation.getErrorMessage!(
+            getNewLayerWithFormula(formula),
+            'col1',
+            indexPattern,
+            operationDefinitionMap
+          )
+        ).toEqual(undefined);
+      }
+    });
+
+    it('returns an error for a query not wrapped in single quotes', () => {
+      const formulas = [
+        `count(kql="")`,
+        `count(kql='")`,
+        `count(kql="')`,
+        `count(kql="category.keyword: *")`,
+        `count(kql='category.keyword: *")`,
+        `count(kql="category.keyword: *')`,
+        `count(kql='category.keyword: *)`,
+        `count(kql=category.keyword: *')`,
+        `count(kql=category.keyword: *)`,
+        `count(kql="category.keyword: "Men's Clothing" or category.keyword: "Men's Shoes"")`,
+        `count(lucene="category.keyword: *")`,
+        `count(lucene=category.keyword: *)`,
+        `count(lucene=category.keyword: *) + average(bytes)`,
+        `count(lucene='category.keyword: *') + count(kql=category.keyword: *)`,
+        `count(lucene='category.keyword: *") + count(kql='category.keyword: *")`,
+        `count(lucene='category.keyword: *') + count(kql=category.keyword: *, kql='category.keyword: *')`,
+        `count(lucene='category.keyword: *') + count(kql="category.keyword: *")`,
+        `moving_average(count(kql=category.keyword: *), window=7, kql=category.keywork: *)`,
+        `moving_average(
+          cumulative_sum(
+             7 * clamp(sum(bytes), 0, last_value(memory) + max(memory))
+          ), window=10, kql=category.keywork: *
+        )`,
+      ];
+      for (const formula of formulas) {
+        expect(
+          formulaOperation.getErrorMessage!(
+            getNewLayerWithFormula(formula),
+            'col1',
+            indexPattern,
+            operationDefinitionMap
+          )
+        ).toEqual(expect.arrayContaining([expect.stringMatching(`Single quotes are required`)]));
+      }
+    });
+
+    it('it returns parse fail error rather than query message if the formula is only a query condition (false positive cases for query checks)', () => {
+      const formulas = [
+        `kql="category.keyword: *"`,
+        `kql=category.keyword: *`,
+        `kql='category.keyword: *'`,
+        `(kql="category.keyword: *")`,
+        `(kql=category.keyword: *)`,
+        `(lucene="category.keyword: *")`,
+        `(lucene=category.keyword: *)`,
+        `(lucene='category.keyword: *') + (kql=category.keyword: *)`,
+        `(lucene='category.keyword: *') + (kql=category.keyword: *, kql='category.keyword: *')`,
+        `(lucene='category.keyword: *') + (kql="category.keyword: *")`,
+        `((kql=category.keyword: *), window=7, kql=category.keywork: *)`,
+        `(, window=10, kql=category.keywork: *)`,
+        `(
+          , window=10, kql=category.keywork: *
+        )`,
+      ];
+      for (const formula of formulas) {
+        expect(
+          formulaOperation.getErrorMessage!(
+            getNewLayerWithFormula(formula),
+            'col1',
+            indexPattern,
+            operationDefinitionMap
+          )
+        ).toEqual([`The Formula ${formula} cannot be parsed`]);
+      }
+    });
+
+    it('returns no error for a query wrapped in single quotes but with some whitespaces', () => {
+      const formulas = [
+        `count(kql ='category.keyword: *')`,
+        `count(kql = 'category.keyword: *')`,
+        `count(kql =    'category.keyword: *')`,
+      ];
+      for (const formula of formulas) {
+        expect(
+          formulaOperation.getErrorMessage!(
+            getNewLayerWithFormula(formula),
+            'col1',
+            indexPattern,
+            operationDefinitionMap
+          )
+        ).toEqual(undefined);
+      }
+    });
+
+    it('returns an error for multiple queries submitted for the same function', () => {
+      expect(
+        formulaOperation.getErrorMessage!(
+          getNewLayerWithFormula(`count(kql='category.keyword: *', lucene='category.keyword: *')`),
+          'col1',
+          indexPattern,
+          operationDefinitionMap
+        )
+      ).toEqual(['Use only one of kql= or lucene=, not both']);
+    });
+
+    it("returns a clear error when there's a missing field for a function", () => {
+      for (const fn of ['average', 'terms', 'max', 'sum']) {
+        expect(
+          formulaOperation.getErrorMessage!(
+            getNewLayerWithFormula(`${fn}()`),
+            'col1',
+            indexPattern,
+            operationDefinitionMap
+          )
+        ).toEqual([`The first argument for ${fn} should be a field name. Found no field`]);
+      }
+    });
+
+    it("returns a clear error when there's a missing function for a fullReference operation", () => {
+      for (const fn of ['cumulative_sum', 'derivative']) {
+        expect(
+          formulaOperation.getErrorMessage!(
+            getNewLayerWithFormula(`${fn}()`),
+            'col1',
+            indexPattern,
+            operationDefinitionMap
+          )
+        ).toEqual([`The first argument for ${fn} should be a operation name. Found no operation`]);
+      }
+    });
+
     it('returns no error if a math operation is passed to fullReference operations', () => {
       const formulas = [
         'derivative(7+1)',
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx
index de7ecb4bc75da..3ed5090690876 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx
@@ -10,8 +10,11 @@ import { OperationDefinition } from '../index';
 import { ReferenceBasedIndexPatternColumn } from '../column_types';
 import { IndexPattern } from '../../../types';
 import { runASTValidation, tryToParse } from './validation';
+import { MemoizedFormulaEditor } from './editor';
 import { regenerateLayerFromAst } from './parse';
 import { generateFormula } from './generate';
+import { filterByVisibleOperation } from './util';
+import { getManagedColumnsFrom } from '../../layer_helpers';
 
 const defaultLabel = i18n.translate('xpack.lens.indexPattern.formulaLabel', {
   defaultMessage: 'Formula',
@@ -38,7 +41,7 @@ export const formulaOperation: OperationDefinition<
 > = {
   type: 'formula',
   displayName: defaultLabel,
-  getDefaultLabel: (column, indexPattern) => defaultLabel,
+  getDefaultLabel: (column, indexPattern) => column.params.formula ?? defaultLabel,
   input: 'managedReference',
   hidden: true,
   getDisabledStatus(indexPattern: IndexPattern) {
@@ -49,13 +52,32 @@ export const formulaOperation: OperationDefinition<
     if (!column.params.formula || !operationDefinitionMap) {
       return;
     }
-    const { root, error } = tryToParse(column.params.formula);
+
+    const visibleOperationsMap = filterByVisibleOperation(operationDefinitionMap);
+    const { root, error } = tryToParse(column.params.formula, visibleOperationsMap);
     if (error || !root) {
       return [error!.message];
     }
 
-    const errors = runASTValidation(root, layer, indexPattern, operationDefinitionMap);
-    return errors.length ? errors.map(({ message }) => message) : undefined;
+    const errors = runASTValidation(root, layer, indexPattern, visibleOperationsMap);
+
+    if (errors.length) {
+      return errors.map(({ message }) => message);
+    }
+
+    const managedColumns = getManagedColumnsFrom(columnId, layer.columns);
+    const innerErrors = managedColumns
+      .flatMap(([id, col]) => {
+        const def = visibleOperationsMap[col.operationType];
+        if (def?.getErrorMessage) {
+          const messages = def.getErrorMessage(layer, id, indexPattern, visibleOperationsMap);
+          return messages ? { message: messages.join(', ') } : [];
+        }
+        return [];
+      })
+      .filter((marker) => marker);
+
+    return innerErrors.length ? innerErrors.map(({ message }) => message) : undefined;
   },
   getPossibleOperation() {
     return {
@@ -72,8 +94,8 @@ export const formulaOperation: OperationDefinition<
     const label = !params?.isFormulaBroken
       ? useDisplayLabel
         ? currentColumn.label
-        : params?.formula
-      : '';
+        : params?.formula ?? defaultLabel
+      : defaultLabel;
 
     return [
       {
@@ -81,21 +103,23 @@ export const formulaOperation: OperationDefinition<
         function: 'mapColumn',
         arguments: {
           id: [columnId],
-          name: [label || ''],
+          name: [label || defaultLabel],
           exp: [
             {
               type: 'expression',
-              chain: [
-                {
-                  type: 'function',
-                  function: 'math',
-                  arguments: {
-                    expression: [
-                      currentColumn.references.length ? `"${currentColumn.references[0]}"` : ``,
-                    ],
-                  },
-                },
-              ],
+              chain: currentColumn.references.length
+                ? [
+                    {
+                      type: 'function',
+                      function: 'math',
+                      arguments: {
+                        expression: [
+                          currentColumn.references.length ? `"${currentColumn.references[0]}"` : ``,
+                        ],
+                      },
+                    },
+                  ]
+                : [],
             },
           ],
         },
@@ -119,7 +143,7 @@ export const formulaOperation: OperationDefinition<
       prevFormat = { format: previousColumn.params.format };
     }
     return {
-      label: 'Formula',
+      label: previousFormula || defaultLabel,
       dataType: 'number',
       operationType: 'formula',
       isBucketed: false,
@@ -152,4 +176,6 @@ export const formulaOperation: OperationDefinition<
     );
     return newLayer;
   },
+
+  paramEditor: MemoizedFormulaEditor,
 };
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/math_examples.md b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/math_examples.md
new file mode 100644
index 0000000000000..ae244109ed53e
--- /dev/null
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/math_examples.md
@@ -0,0 +1,28 @@
+Basic numeric functions that we already support in Lens:
+
+count()
+count(normalize_unit='1s')
+sum(field name)
+avg(field name)
+moving_average(sum(field name), window=5)
+moving_average(sum(field name), window=5, normalize_unit='1s')
+counter_rate(field name, normalize_unit='1s')
+differences(count())
+differences(sum(bytes), normalize_unit='1s')
+last_value(bytes, sort=timestamp)
+percentile(bytes, percent=95)
+
+Adding features beyond what we already support. New features are:
+
+* Filtering
+* Math across series
+* Time offset
+
+count() * 100
+(count() / count(offset=-7d)) + min(field name)
+sum(field name, filter='field.keyword: "KQL autocomplete inside math" AND field.value > 100')
+
+What about custom formatting using string manipulation? Probably not...
+
+(avg(bytes) / 1000) + 'kb'
+  
\ No newline at end of file
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts
index 3bfc6fcbfc011..517cf5f1bbf45 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts
@@ -5,6 +5,7 @@
  * 2.0.
  */
 
+import { i18n } from '@kbn/i18n';
 import { isObject } from 'lodash';
 import type { TinymathAST, TinymathVariable, TinymathLocation } from '@kbn/tinymath';
 import { OperationDefinition, GenericOperationDefinition, IndexPatternColumn } from '../index';
@@ -12,7 +13,12 @@ import { IndexPattern, IndexPatternLayer } from '../../../types';
 import { mathOperation } from './math';
 import { documentField } from '../../../document_field';
 import { runASTValidation, shouldHaveFieldArgument, tryToParse } from './validation';
-import { findVariables, getOperationParams, groupArgsByType } from './util';
+import {
+  filterByVisibleOperation,
+  findVariables,
+  getOperationParams,
+  groupArgsByType,
+} from './util';
 import { FormulaIndexPatternColumn } from './formula';
 import { getColumnOrder } from '../../layer_helpers';
 
@@ -27,7 +33,7 @@ function parseAndExtract(
   indexPattern: IndexPattern,
   operationDefinitionMap: Record<string, GenericOperationDefinition>
 ) {
-  const { root, error } = tryToParse(text);
+  const { root, error } = tryToParse(text, operationDefinitionMap);
   if (error || !root) {
     return { extracted: [], isValid: false };
   }
@@ -61,9 +67,9 @@ function extractColumns(
     const nodeOperation = operations[node.name];
     if (!nodeOperation) {
       // it's a regular math node
-      const consumedArgs = node.args.map(parseNode).filter(Boolean) as Array<
-        number | TinymathVariable
-      >;
+      const consumedArgs = node.args
+        .map(parseNode)
+        .filter((n) => typeof n !== 'undefined' && n !== null) as Array<number | TinymathVariable>;
       return {
         ...node,
         args: consumedArgs,
@@ -168,7 +174,7 @@ export function regenerateLayerFromAst(
     layer,
     columnId,
     indexPattern,
-    operationDefinitionMap
+    filterByVisibleOperation(operationDefinitionMap)
   );
 
   const columns = { ...layer.columns };
@@ -188,6 +194,12 @@ export function regenerateLayerFromAst(
 
   columns[columnId] = {
     ...currentColumn,
+    label: !currentColumn.customLabel
+      ? text ??
+        i18n.translate('xpack.lens.indexPattern.formulaLabel', {
+          defaultMessage: 'Formula',
+        })
+      : currentColumn.label,
     params: {
       ...currentColumn.params,
       formula: text,
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts
index 5d9a8647eb7ab..dd95ebdec5b8a 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts
@@ -13,7 +13,7 @@ import type {
   TinymathNamedArgument,
   TinymathVariable,
 } from 'packages/kbn-tinymath';
-import type { OperationDefinition, IndexPatternColumn } from '../index';
+import type { OperationDefinition, IndexPatternColumn, GenericOperationDefinition } from '../index';
 import type { GroupedNodes } from './types';
 
 export function groupArgsByType(args: TinymathAST[]) {
@@ -66,6 +66,16 @@ export function getOperationParams(
   }, {});
 }
 
+function getTypeI18n(type: string) {
+  if (type === 'number') {
+    return i18n.translate('xpack.lens.formula.number', { defaultMessage: 'number' });
+  }
+  if (type === 'string') {
+    return i18n.translate('xpack.lens.formula.string', { defaultMessage: 'string' });
+  }
+  return '';
+}
+
 // Todo: i18n everything here
 export const tinymathFunctions: Record<
   string,
@@ -73,145 +83,254 @@ export const tinymathFunctions: Record<
     positionalArguments: Array<{
       name: string;
       optional?: boolean;
+      defaultValue?: string | number;
+      type?: string;
     }>;
-    // help: React.ReactElement;
     // Help is in Markdown format
     help: string;
   }
 > = {
   add: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }) },
-      { name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }),
+        type: getTypeI18n('number'),
+      },
+      {
+        name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }),
+        type: getTypeI18n('number'),
+      },
     ],
     help: `
+Adds up two numbers.
 Also works with + symbol
-Example: ${'`count() + sum(bytes)`'}
-Example: ${'`add(count(), 5)`'}
+
+Example: Calculate the sum of two fields
+
+${'`sum(price) + sum(tax)`'}
+
+Example: Offset count by a static value
+
+${'`add(count(), 5)`'}
     `,
   },
   subtract: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }) },
-      { name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }),
+        type: getTypeI18n('number'),
+      },
+      {
+        name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }),
+        type: getTypeI18n('number'),
+      },
     ],
     help: `
+Subtracts the first number from the second number.
 Also works with ${'`-`'} symbol
-Example: ${'`subtract(sum(bytes), avg(bytes))`'}
+
+Example: Calculate the range of a field
+${'`subtract(max(bytes), min(bytes))`'}
     `,
   },
   multiply: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }) },
-      { name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }),
+        type: getTypeI18n('number'),
+      },
+      {
+        name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }),
+        type: getTypeI18n('number'),
+      },
     ],
     help: `
-Also works with ${'`*`'} symbol
-Example: ${'`multiply(sum(bytes), 2)`'}
+Multiplies two numbers.
+Also works with ${'`*`'} symbol.
+
+Example: Calculate price after current tax rate
+${'`sum(bytes) * last_value(tax_rate)`'}
+
+Example: Calculate price after constant tax rate
+${'`multiply(sum(price), 1.2)`'}
     `,
   },
   divide: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }) },
-      { name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }),
+        type: getTypeI18n('number'),
+      },
+      {
+        name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }),
+        type: getTypeI18n('number'),
+      },
     ],
     help: `
+Divides the first number by the second number.
 Also works with ${'`/`'} symbol
-Example: ${'`ceil(sum(bytes))`'}
+
+Example: Calculate profit margin 
+${'`sum(profit) / sum(revenue)`'}
+
+Example: ${'`divide(sum(bytes), 2)`'}
     `,
   },
   abs: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }),
+        type: getTypeI18n('number'),
+      },
     ],
     help: `
-Absolute value
-Example: ${'`abs(sum(bytes))`'}
+Calculates absolute value. A negative value is multiplied by -1, a positive value stays the same.
+
+Example: Calculate average distance to sea level ${'`abs(average(altitude))`'}
     `,
   },
   cbrt: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }),
+        type: getTypeI18n('number'),
+      },
     ],
     help: `
-Cube root of value
-Example: ${'`cbrt(sum(bytes))`'}
+Cube root of value.
+
+Example: Calculate side length from volume
+${'`cbrt(last_value(volume))`'}
     `,
   },
   ceil: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }),
+        type: getTypeI18n('number'),
+      },
     ],
+    // signature: 'ceil(value: number)',
     help: `
-Ceiling of value, rounds up
-Example: ${'`ceil(sum(bytes))`'}
+Ceiling of value, rounds up.
+
+Example: Round up price to the next dollar 
+${'`ceil(sum(price))`'}
     `,
   },
   clamp: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
-      { name: i18n.translate('xpack.lens.formula.min', { defaultMessage: 'min' }) },
-      { name: i18n.translate('xpack.lens.formula.max', { defaultMessage: 'max' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }),
+        type: getTypeI18n('number'),
+      },
+      {
+        name: i18n.translate('xpack.lens.formula.min', { defaultMessage: 'min' }),
+        type: getTypeI18n('number'),
+      },
+      {
+        name: i18n.translate('xpack.lens.formula.max', { defaultMessage: 'max' }),
+        type: getTypeI18n('number'),
+      },
     ],
+    // signature: 'clamp(value: number, minimum: number, maximum: number)',
     help: `
-Limits the value from a minimum to maximum
-Example: ${'`ceil(sum(bytes))`'}
-    `,
+Limits the value from a minimum to maximum.
+
+Example: Make sure to catch outliers
+\`\`\`
+clamp(
+  average(bytes),
+  percentile(bytes, percentile=5),
+  percentile(bytes, percentile=95)
+)
+\`\`\`
+`,
   },
   cube: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }),
+        type: getTypeI18n('number'),
+      },
     ],
     help: `
-Limits the value from a minimum to maximum
-Example: ${'`ceil(sum(bytes))`'}
+Calculates the cube of a number.
+
+Example: Calculate volume from side length
+${'`cube(last_value(length))`'}
     `,
   },
   exp: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }),
+        type: getTypeI18n('number'),
+      },
     ],
     help: `
-Raises <em>e</em> to the nth power.
-Example: ${'`exp(sum(bytes))`'}
+Raises *e* to the nth power.
+
+Example: Calculate the natural exponential function
+
+${'`exp(last_value(duration))`'}
     `,
   },
   fix: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }),
+        type: getTypeI18n('number'),
+      },
     ],
     help: `
 For positive values, takes the floor. For negative values, takes the ceiling.
-Example: ${'`fix(sum(bytes))`'}
+
+Example: Rounding towards zero
+${'`fix(sum(profit))`'}
     `,
   },
   floor: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }),
+        type: getTypeI18n('number'),
+      },
     ],
     help: `
 Round down to nearest integer value
-Example: ${'`floor(sum(bytes))`'}
+
+Example: Round down a price
+${'`floor(sum(price))`'}
     `,
   },
   log: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }),
+        type: getTypeI18n('number'),
+      },
       {
         name: i18n.translate('xpack.lens.formula.base', { defaultMessage: 'base' }),
         optional: true,
+        defaultValue: 'e',
+        type: getTypeI18n('number'),
       },
     ],
     help: `
-Logarithm with optional base. The natural base <em>e</em> is used as default.
-Example: ${'`log(sum(bytes))`'}
-Example: ${'`log(sum(bytes), 2)`'}
+Logarithm with optional base. The natural base *e* is used as default.
+
+Example: Calculate number of bits required to store values
+\`\`\`
+log(sum(bytes))
+log(sum(bytes), 2)
+\`\`\`
     `,
   },
   // TODO: check if this is valid for Tinymath
   //   log10: {
   //     positionalArguments: [
-  //       { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
+  //       { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), type: getTypeI18n('number') },
   //     ],
   //     help: `
   // Base 10 logarithm.
@@ -220,59 +339,89 @@ Example: ${'`log(sum(bytes), 2)`'}
   //   },
   mod: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }),
+        type: getTypeI18n('number'),
+      },
       {
         name: i18n.translate('xpack.lens.formula.base', { defaultMessage: 'base' }),
-        optional: true,
+        type: getTypeI18n('number'),
       },
     ],
     help: `
 Remainder after dividing the function by a number
-Example: ${'`mod(sum(bytes), 2)`'}
+
+Example: Calculate last three digits of a value
+${'`mod(sum(price), 1000)`'}
     `,
   },
   pow: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }),
+        type: getTypeI18n('number'),
+      },
       {
         name: i18n.translate('xpack.lens.formula.base', { defaultMessage: 'base' }),
+        type: getTypeI18n('number'),
       },
     ],
     help: `
 Raises the value to a certain power. The second argument is required
-Example: ${'`pow(sum(bytes), 3)`'}
+
+Example: Calculate volume based on side length
+${'`pow(last_value(length), 3)`'}
     `,
   },
   round: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }),
+        type: getTypeI18n('number'),
+      },
       {
         name: i18n.translate('xpack.lens.formula.decimals', { defaultMessage: 'decimals' }),
         optional: true,
+        defaultValue: 0,
+        type: getTypeI18n('number'),
       },
     ],
     help: `
 Rounds to a specific number of decimal places, default of 0
-Example: ${'`round(sum(bytes))`'}
-Example: ${'`round(sum(bytes), 2)`'}
+
+Examples: Round to the cent
+\`\`\`
+round(sum(bytes))
+round(sum(bytes), 2)
+\`\`\`
     `,
   },
   sqrt: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }),
+        type: getTypeI18n('number'),
+      },
     ],
     help: `
 Square root of a positive value only
-Example: ${'`sqrt(sum(bytes))`'}
+
+Example: Calculate side length based on area
+${'`sqrt(last_value(area))`'}
     `,
   },
   square: {
     positionalArguments: [
-      { name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
+      {
+        name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }),
+        type: getTypeI18n('number'),
+      },
     ],
     help: `
 Raise the value to the 2nd power
-Example: ${'`square(sum(bytes))`'}
+
+Example: Calculate area based on side length
+${'`square(last_value(length))`'}
     `,
   },
 };
@@ -315,3 +464,11 @@ export function findVariables(node: TinymathAST | string): TinymathVariable[] {
   }
   return node.args.flatMap(findVariables);
 }
+
+export function filterByVisibleOperation(
+  operationDefinitionMap: Record<string, GenericOperationDefinition>
+) {
+  return Object.fromEntries(
+    Object.entries(operationDefinitionMap).filter(([, operation]) => !operation.hidden)
+  );
+}
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts
index 5145c7959f1bb..992b8ee2422e9 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts
@@ -5,7 +5,7 @@
  * 2.0.
  */
 
-import { isObject } from 'lodash';
+import { isObject, partition } from 'lodash';
 import { i18n } from '@kbn/i18n';
 import { parse, TinymathLocation } from '@kbn/tinymath';
 import type { TinymathAST, TinymathFunction, TinymathNamedArgument } from '@kbn/tinymath';
@@ -58,6 +58,10 @@ interface ValidationErrors {
     message: string;
     type: { operation: string; count: number; params: string };
   };
+  tooManyQueries: {
+    message: string;
+    type: {};
+  };
 }
 type ErrorTypes = keyof ValidationErrors;
 type ErrorValues<K extends ErrorTypes> = ValidationErrors[K]['type'];
@@ -90,15 +94,76 @@ export function hasInvalidOperations(
   return {
     // avoid duplicates
     names: Array.from(new Set(nodes.map(({ name }) => name))),
-    locations: nodes.map(({ location }) => location),
+    locations: nodes.map(({ location }) => location).filter((a) => a) as TinymathLocation[],
   };
 }
 
+export const getRawQueryValidationError = (text: string, operations: Record<string, unknown>) => {
+  // try to extract the query context here
+  const singleLine = text.split('\n').join('');
+  const allArgs = singleLine.split(',').filter((args) => /(kql|lucene)/.test(args));
+  // check for the presence of a valid ES operation
+  const containsOneValidOperation = Object.keys(operations).some((operation) =>
+    singleLine.includes(operation)
+  );
+  // no args or no valid operation, no more work to do here
+  if (allArgs.length === 0 || !containsOneValidOperation) {
+    return;
+  }
+  // at this point each entry in allArgs may contain one or more
+  // in the worst case it would be a math chain of count operation
+  // For instance: count(kql=...) + count(lucene=...) - count(kql=...)
+  // therefore before partition them, split them by "count" keywork and filter only string with a length
+  const flattenArgs = allArgs.flatMap((arg) =>
+    arg.split('count').filter((subArg) => /(kql|lucene)/.test(subArg))
+  );
+  const [kqlQueries, luceneQueries] = partition(flattenArgs, (arg) => /kql/.test(arg));
+  const errors = [];
+  for (const kqlQuery of kqlQueries) {
+    const result = validateQueryQuotes(kqlQuery, 'kql');
+    if (result) {
+      errors.push(result);
+    }
+  }
+  for (const luceneQuery of luceneQueries) {
+    const result = validateQueryQuotes(luceneQuery, 'lucene');
+    if (result) {
+      errors.push(result);
+    }
+  }
+  return errors.length ? errors : undefined;
+};
+
+const validateQueryQuotes = (rawQuery: string, language: 'kql' | 'lucene') => {
+  // check if the raw argument has the minimal requirements
+  // use the rest operator here to handle cases where comparison operations are used in the query
+  const [, ...rawValue] = rawQuery.split('=');
+  const fullRawValue = (rawValue || ['']).join('');
+  const cleanedRawValue = fullRawValue.trim();
+  // it must start with a single quote, and quotes must have a closure
+  if (
+    cleanedRawValue.length &&
+    (cleanedRawValue[0] !== "'" || !/'\s*([^']+?)\s*'/.test(fullRawValue)) &&
+    // there's a special case when it's valid as two single quote strings
+    cleanedRawValue !== "''"
+  ) {
+    return i18n.translate('xpack.lens.indexPattern.formulaOperationQueryError', {
+      defaultMessage: `Single quotes are required for {language}='' at {rawQuery}`,
+      values: { language, rawQuery },
+    });
+  }
+};
+
 export const getQueryValidationError = (
-  query: string,
-  language: 'kql' | 'lucene',
+  { value: query, name: language, text }: TinymathNamedArgument,
   indexPattern: IndexPattern
 ): string | undefined => {
+  // check if the raw argument has the minimal requirements
+  const result = validateQueryQuotes(text, language as 'kql' | 'lucene');
+  // forward the error here is ok?
+  if (result) {
+    return result;
+  }
   try {
     if (language === 'kql') {
       esKuery.toElasticsearchQuery(esKuery.fromKueryExpression(query), indexPattern);
@@ -113,7 +178,7 @@ export const getQueryValidationError = (
 
 function getMessageFromId<K extends ErrorTypes>({
   messageId,
-  values: { ...values },
+  values,
   locations,
 }: {
   messageId: K;
@@ -203,6 +268,11 @@ function getMessageFromId<K extends ErrorTypes>({
         values: { operation: out.operation, count: out.count, params: out.params },
       });
       break;
+    case 'tooManyQueries':
+      message = i18n.translate('xpack.lens.indexPattern.formulaOperationDoubleQueryError', {
+        defaultMessage: 'Use only one of kql= or lucene=, not both',
+      });
+      break;
     // case 'mathRequiresFunction':
     //   message = i18n.translate('xpack.lens.indexPattern.formulaMathRequiresFunctionLabel', {
     //     defaultMessage; 'The function {name} requires an Elasticsearch function',
@@ -218,12 +288,22 @@ function getMessageFromId<K extends ErrorTypes>({
 }
 
 export function tryToParse(
-  formula: string
+  formula: string,
+  operations: Record<string, unknown>
 ): { root: TinymathAST; error: null } | { root: null; error: ErrorWrapper } {
   let root;
   try {
     root = parse(formula);
   } catch (e) {
+    // A tradeoff is required here, unless we want to reimplement a full parser
+    // Internally the function has the following logic:
+    // * if the formula contains no existing ES operation, assume it's a plain parse failure
+    // * if the formula contains at least one existing operation, check for query problems
+    const maybeQueryProblems = getRawQueryValidationError(formula, operations);
+    if (maybeQueryProblems) {
+      // need to emulate an error shape here
+      return { root: null, error: { message: maybeQueryProblems[0], locations: [] } };
+    }
     return {
       root: null,
       error: getMessageFromId({
@@ -319,7 +399,10 @@ function getQueryValidationErrors(
   const errors: ErrorWrapper[] = [];
   (namedArguments ?? []).forEach((arg) => {
     if (arg.name === 'kql' || arg.name === 'lucene') {
-      const message = getQueryValidationError(arg.value, arg.name, indexPattern);
+      const message = getQueryValidationError(
+        arg as TinymathNamedArgument & { name: 'kql' | 'lucene' },
+        indexPattern
+      );
       if (message) {
         errors.push({
           message,
@@ -331,6 +414,12 @@ function getQueryValidationErrors(
   return errors;
 }
 
+function checkSingleQuery(namedArguments: TinymathNamedArgument[] | undefined) {
+  return namedArguments
+    ? namedArguments.filter((arg) => arg.name === 'kql' || arg.name === 'lucene').length > 1
+    : undefined;
+}
+
 function validateNameArguments(
   node: TinymathFunction,
   nodeOperation:
@@ -349,7 +438,7 @@ function validateNameArguments(
           operation: node.name,
           params: missingParams.map(({ name }) => name).join(', '),
         },
-        locations: [node.location],
+        locations: node.location ? [node.location] : [],
       })
     );
   }
@@ -362,7 +451,7 @@ function validateNameArguments(
           operation: node.name,
           params: wrongTypeParams.map(({ name }) => name).join(', '),
         },
-        locations: [node.location],
+        locations: node.location ? [node.location] : [],
       })
     );
   }
@@ -375,7 +464,7 @@ function validateNameArguments(
           operation: node.name,
           params: duplicateParams.join(', '),
         },
-        locations: [node.location],
+        locations: node.location ? [node.location] : [],
       })
     );
   }
@@ -383,6 +472,16 @@ function validateNameArguments(
   if (queryValidationErrors.length) {
     errors.push(...queryValidationErrors);
   }
+  const hasTooManyQueries = checkSingleQuery(namedArguments);
+  if (hasTooManyQueries) {
+    errors.push(
+      getMessageFromId({
+        messageId: 'tooManyQueries',
+        values: {},
+        locations: node.location ? [node.location] : [],
+      })
+    );
+  }
   return errors;
 }
 
@@ -426,7 +525,7 @@ function runFullASTValidation(
                     type: 'field',
                     argument: `math operation`,
                   },
-                  locations: [node.location],
+                  locations: node.location ? [node.location] : [],
                 })
               );
             } else {
@@ -436,9 +535,13 @@ function runFullASTValidation(
                   values: {
                     operation: node.name,
                     type: 'field',
-                    argument: getValueOrName(firstArg),
+                    argument:
+                      getValueOrName(firstArg) ||
+                      i18n.translate('xpack.lens.indexPattern.formulaNoFieldForOperation', {
+                        defaultMessage: 'no field',
+                      }),
                   },
-                  locations: [node.location],
+                  locations: node.location ? [node.location] : [],
                 })
               );
             }
@@ -452,7 +555,7 @@ function runFullASTValidation(
                 values: {
                   operation: node.name,
                 },
-                locations: [node.location],
+                locations: node.location ? [node.location] : [],
               })
             );
           }
@@ -464,7 +567,7 @@ function runFullASTValidation(
               values: {
                 operation: node.name,
               },
-              locations: [node.location],
+              locations: node.location ? [node.location] : [],
             })
           );
         } else {
@@ -493,9 +596,13 @@ function runFullASTValidation(
               values: {
                 operation: node.name,
                 type: 'operation',
-                argument: getValueOrName(firstArg),
+                argument:
+                  getValueOrName(firstArg) ||
+                  i18n.translate('xpack.lens.indexPattern.formulaNoOperation', {
+                    defaultMessage: 'no operation',
+                  }),
               },
-              locations: [node.location],
+              locations: node.location ? [node.location] : [],
             })
           );
         }
@@ -506,7 +613,7 @@ function runFullASTValidation(
               values: {
                 operation: node.name,
               },
-              locations: [node.location],
+              locations: node.location ? [node.location] : [],
             })
           );
         } else {
@@ -606,7 +713,11 @@ export function validateParams(
 }
 
 export function shouldHaveFieldArgument(node: TinymathFunction) {
-  return !['count'].includes(node.name);
+  return hasFunctionFieldArgument(node.name);
+}
+
+export function hasFunctionFieldArgument(type: string) {
+  return !['count'].includes(type);
 }
 
 export function isFirstArgumentValidType(arg: TinymathAST, type: TinymathNodeTypes['type']) {
@@ -628,7 +739,7 @@ export function validateMathNodes(root: TinymathAST, missingVariableSet: Set<str
             type: 'operation',
             argument: `()`,
           },
-          locations: [node.location],
+          locations: node.location ? [node.location] : [],
         })
       );
     }
@@ -640,7 +751,7 @@ export function validateMathNodes(root: TinymathAST, missingVariableSet: Set<str
           values: {
             operation: node.name,
           },
-          locations: [node.location],
+          locations: node.location ? [node.location] : [],
         })
       );
     }
@@ -659,7 +770,7 @@ export function validateMathNodes(root: TinymathAST, missingVariableSet: Set<str
           values: {
             operation: node.name,
           },
-          locations: [node.location],
+          locations: node.location ? [node.location] : [],
         })
       );
     }
@@ -678,7 +789,7 @@ export function validateMathNodes(root: TinymathAST, missingVariableSet: Set<str
             count: mandatoryArguments.length - node.args.length,
             params: missingArgs.map(({ name }) => name).join(', '),
           },
-          locations: [node.location],
+          locations: node.location ? [node.location] : [],
         })
       );
     }
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts
index 164415c1a1f6f..a7bf415817797 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts
@@ -153,6 +153,9 @@ export interface ParamEditorProps<C> {
   updateLayer: (
     setter: IndexPatternLayer | ((prevLayer: IndexPatternLayer) => IndexPatternLayer)
   ) => void;
+  toggleFullscreen: () => void;
+  setIsCloseable: (isCloseable: boolean) => void;
+  isFullscreen: boolean;
   columnId: string;
   indexPattern: IndexPattern;
   uiSettings: IUiSettingsClient;
@@ -279,6 +282,11 @@ interface BaseOperationDefinitionProps<C extends BaseIndexPatternColumn> {
    * Operations can be used as middleware for other operations, hence not shown in the panel UI
    */
   hidden?: boolean;
+  documentation?: {
+    signature: string;
+    description: string;
+    section: 'elasticsearch' | 'calculation';
+  };
 }
 
 interface BaseBuildColumnArgs {
@@ -290,6 +298,7 @@ interface OperationParam {
   name: string;
   type: string;
   required?: boolean;
+  defaultValue?: string | number;
 }
 
 interface FieldlessOperationDefinition<C extends BaseIndexPatternColumn> {
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx
index 15ce3bdcd0b0f..2ad91a7ba91a1 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx
@@ -30,6 +30,9 @@ const defaultProps = {
     hasRestrictions: false,
   } as IndexPattern,
   operationDefinitionMap: {},
+  isFullscreen: false,
+  toggleFullscreen: jest.fn(),
+  setIsCloseable: jest.fn(),
 };
 
 describe('last_value', () => {
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx
index bde80accfbc67..bfc5ce39bc939 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx
@@ -277,4 +277,20 @@ export const lastValueOperation: OperationDefinition<LastValueIndexPatternColumn
       </>
     );
   },
+  documentation: {
+    section: 'elasticsearch',
+    signature: i18n.translate('xpack.lens.indexPattern.lastValue.signature', {
+      defaultMessage: 'field: string',
+    }),
+    description: i18n.translate('xpack.lens.indexPattern.lastValue.documentation', {
+      defaultMessage: `
+Returns the value of a field from the last document, ordered by the default time field of the index pattern.
+
+This function is usefull the retrieve the latest state of an entity.
+
+Example: Get the current status of server A: 
+\`last_value(server.status, kql=\'server.name="A"\')\`
+      `,
+    }),
+  },
 };
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx
index 54a3ff0eb8bdb..58fe91b23f2c7 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx
@@ -42,6 +42,7 @@ const supportedTypes = ['number', 'histogram'];
 function buildMetricOperation<T extends MetricColumn<string>>({
   type,
   displayName,
+  description,
   ofName,
   priority,
   optionalTimeScaling,
@@ -51,6 +52,7 @@ function buildMetricOperation<T extends MetricColumn<string>>({
   ofName: (name: string) => string;
   priority?: number;
   optionalTimeScaling?: boolean;
+  description?: string;
 }) {
   const labelLookup = (name: string, column?: BaseIndexPatternColumn) => {
     const label = ofName(name);
@@ -67,6 +69,7 @@ function buildMetricOperation<T extends MetricColumn<string>>({
     type,
     priority,
     displayName,
+    description,
     input: 'field',
     timeScalingMode: optionalTimeScaling ? 'optional' : undefined,
     getPossibleOperationForField: ({ aggregationRestrictions, aggregatable, type: fieldType }) => {
@@ -131,6 +134,26 @@ function buildMetricOperation<T extends MetricColumn<string>>({
     getErrorMessage: (layer, columnId, indexPattern) =>
       getInvalidFieldMessage(layer.columns[columnId] as FieldBasedIndexPatternColumn, indexPattern),
     filterable: true,
+    documentation: {
+      section: 'elasticsearch',
+      signature: i18n.translate('xpack.lens.indexPattern.metric.signature', {
+        defaultMessage: 'field: string',
+      }),
+      description: i18n.translate('xpack.lens.indexPattern.metric.documentation', {
+        defaultMessage: `
+Returns the {metric} of a field. This function only works for number fields.
+
+Example: Get the {metric} of price:
+\`{metric}(price)\`
+
+Example: Get the {metric} of price for orders from the UK:
+\`{metric}(price, kql='location:UK')\`
+      `,
+        values: {
+          metric: type,
+        },
+      }),
+    },
     shiftable: true,
   } as OperationDefinition<T, 'field'>;
 }
@@ -151,6 +174,10 @@ export const minOperation = buildMetricOperation<MinIndexPatternColumn>({
       defaultMessage: 'Minimum of {name}',
       values: { name },
     }),
+  description: i18n.translate('xpack.lens.indexPattern.min.description', {
+    defaultMessage:
+      'A single-value metrics aggregation that returns the minimum value among the numeric values extracted from the aggregated documents.',
+  }),
 });
 
 export const maxOperation = buildMetricOperation<MaxIndexPatternColumn>({
@@ -163,6 +190,10 @@ export const maxOperation = buildMetricOperation<MaxIndexPatternColumn>({
       defaultMessage: 'Maximum of {name}',
       values: { name },
     }),
+  description: i18n.translate('xpack.lens.indexPattern.max.description', {
+    defaultMessage:
+      'A single-value metrics aggregation that returns the maximum value among the numeric values extracted from the aggregated documents.',
+  }),
 });
 
 export const averageOperation = buildMetricOperation<AvgIndexPatternColumn>({
@@ -176,6 +207,10 @@ export const averageOperation = buildMetricOperation<AvgIndexPatternColumn>({
       defaultMessage: 'Average of {name}',
       values: { name },
     }),
+  description: i18n.translate('xpack.lens.indexPattern.avg.description', {
+    defaultMessage:
+      'A single-value metric aggregation that computes the average of numeric values that are extracted from the aggregated documents',
+  }),
 });
 
 export const sumOperation = buildMetricOperation<SumIndexPatternColumn>({
@@ -190,6 +225,10 @@ export const sumOperation = buildMetricOperation<SumIndexPatternColumn>({
       values: { name },
     }),
   optionalTimeScaling: true,
+  description: i18n.translate('xpack.lens.indexPattern.sum.description', {
+    defaultMessage:
+      'A single-value metrics aggregation that sums up numeric values that are extracted from the aggregated documents.',
+  }),
 });
 
 export const medianOperation = buildMetricOperation<MedianIndexPatternColumn>({
@@ -203,4 +242,8 @@ export const medianOperation = buildMetricOperation<MedianIndexPatternColumn>({
       defaultMessage: 'Median of {name}',
       values: { name },
     }),
+  description: i18n.translate('xpack.lens.indexPattern.median.description', {
+    defaultMessage:
+      'A single-value metrics aggregation that computes the median value that are extracted from the aggregated documents.',
+  }),
 });
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx
index 2b7104112d63e..0a3462ef20f3f 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx
@@ -32,6 +32,9 @@ const defaultProps = {
     hasRestrictions: false,
   } as IndexPattern,
   operationDefinitionMap: {},
+  isFullscreen: false,
+  toggleFullscreen: jest.fn(),
+  setIsCloseable: jest.fn(),
 };
 
 describe('percentile', () => {
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx
index aa8f951d46b4f..39b876050c2ea 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx
@@ -59,7 +59,9 @@ export const percentileOperation: OperationDefinition<PercentileIndexPatternColu
     defaultMessage: 'Percentile',
   }),
   input: 'field',
-  operationParams: [{ name: 'percentile', type: 'number', required: false }],
+  operationParams: [
+    { name: 'percentile', type: 'number', required: false, defaultValue: DEFAULT_PERCENTILE_VALUE },
+  ],
   filterable: true,
   shiftable: true,
   getPossibleOperationForField: ({ aggregationRestrictions, aggregatable, type: fieldType }) => {
@@ -213,4 +215,18 @@ export const percentileOperation: OperationDefinition<PercentileIndexPatternColu
       </EuiFormRow>
     );
   },
+  documentation: {
+    section: 'elasticsearch',
+    signature: i18n.translate('xpack.lens.indexPattern.percentile.signature', {
+      defaultMessage: 'field: string, [percentile]: number',
+    }),
+    description: i18n.translate('xpack.lens.indexPattern.percentile.documentation', {
+      defaultMessage: `
+Returns the specified percentile of the values of a field. This is the value n percent of the values occuring in documents are smaller.
+
+Example: Get the number of bytes larger than 95 % of values:
+\`percentile(bytes, percentile=95)\`
+      `,
+    }),
+  },
 };
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.test.tsx
index 295f988c6e390..ca4e6d5df0a3c 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.test.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.test.tsx
@@ -102,6 +102,9 @@ const defaultOptions = {
     ]),
   },
   operationDefinitionMap: {},
+  isFullscreen: false,
+  toggleFullscreen: jest.fn(),
+  setIsCloseable: jest.fn(),
 };
 
 describe('ranges', () => {
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/terms.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/terms.test.tsx
index b272d1703377c..32b7dfee828fc 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/terms.test.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/terms.test.tsx
@@ -35,6 +35,9 @@ const defaultProps = {
   http: {} as HttpSetup,
   indexPattern: createMockedIndexPattern(),
   operationDefinitionMap: {},
+  isFullscreen: false,
+  toggleFullscreen: jest.fn(),
+  setIsCloseable: jest.fn(),
 };
 
 describe('terms', () => {
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts
index 38bc84ae9af35..ba3bee415f3f4 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts
@@ -24,7 +24,7 @@ import type { IndexPattern, IndexPatternLayer } from '../types';
 import { documentField } from '../document_field';
 import { getFieldByNameFactory } from '../pure_helpers';
 import { generateId } from '../../id_generator';
-import { createMockedFullReference } from './mocks';
+import { createMockedFullReference, createMockedManagedReference } from './mocks';
 
 jest.mock('../operations');
 jest.mock('../../id_generator');
@@ -91,10 +91,13 @@ describe('state_helpers', () => {
 
     // @ts-expect-error we are inserting an invalid type
     operationDefinitionMap.testReference = createMockedFullReference();
+    // @ts-expect-error we are inserting an invalid type
+    operationDefinitionMap.managedReference = createMockedManagedReference();
   });
 
   afterEach(() => {
     delete operationDefinitionMap.testReference;
+    delete operationDefinitionMap.managedReference;
   });
 
   describe('copyColumn', () => {
@@ -102,19 +105,19 @@ describe('state_helpers', () => {
       const source = {
         dataType: 'number' as const,
         isBucketed: false,
-        label: 'Formula',
+        label: 'moving_average(sum(bytes), window=5)',
         operationType: 'formula' as const,
         params: {
           formula: 'moving_average(sum(bytes), window=5)',
           isFormulaBroken: false,
         },
-        references: ['formulaX3'],
+        references: ['formulaX1'],
       };
       const math = {
         customLabel: true,
         dataType: 'number' as const,
         isBucketed: false,
-        label: 'math',
+        label: 'formulaX2',
         operationType: 'math' as const,
         params: { tinymathAst: 'formulaX2' },
         references: ['formulaX2'],
@@ -135,7 +138,7 @@ describe('state_helpers', () => {
         label: 'formulaX2',
         operationType: 'moving_average' as const,
         params: { window: 5 },
-        references: ['formulaX1'],
+        references: ['formulaX0'],
       };
       expect(
         copyColumn({
@@ -387,6 +390,42 @@ describe('state_helpers', () => {
       ).toEqual(expect.objectContaining({ columnOrder: ['col1', 'col2', 'col3'] }));
     });
 
+    it('should not change order of metrics and references on inserting new buckets', () => {
+      const layer: IndexPatternLayer = {
+        indexPatternId: '1',
+        columnOrder: ['col1', 'col2'],
+        columns: {
+          col1: {
+            label: 'Cumulative sum of count of records',
+            dataType: 'number',
+            isBucketed: false,
+
+            // Private
+            operationType: 'cumulative_sum',
+            references: ['col2'],
+          },
+          col2: {
+            label: 'Count of records',
+            dataType: 'document',
+            isBucketed: false,
+
+            // Private
+            operationType: 'count',
+            sourceField: 'Records',
+          },
+        },
+      };
+      expect(
+        insertNewColumn({
+          layer,
+          indexPattern,
+          columnId: 'col3',
+          op: 'filters',
+          visualizationGroups: [],
+        })
+      ).toEqual(expect.objectContaining({ columnOrder: ['col3', 'col1', 'col2'] }));
+    });
+
     it('should insert both incomplete states if the aggregation does not support the field', () => {
       expect(
         insertNewColumn({
@@ -2655,6 +2694,36 @@ describe('state_helpers', () => {
       expect(errors).toHaveLength(1);
     });
 
+    it('should only collect the top level errors from managed references', () => {
+      const notCalledMock = jest.fn();
+      const mock = jest.fn().mockReturnValue(['error 1']);
+      operationDefinitionMap.testReference.getErrorMessage = notCalledMock;
+      operationDefinitionMap.managedReference.getErrorMessage = mock;
+      const errors = getErrorMessages(
+        {
+          indexPatternId: '1',
+          columnOrder: [],
+          columns: {
+            col1:
+              // @ts-expect-error not statically analyzed
+              { operationType: 'managedReference', references: ['col2'] },
+            col2: {
+              // @ts-expect-error not statically analyzed
+              operationType: 'testReference',
+              references: [],
+            },
+          },
+        },
+        indexPattern,
+        {},
+        '1',
+        {}
+      );
+      expect(notCalledMock).not.toHaveBeenCalled();
+      expect(mock).toHaveBeenCalledTimes(1);
+      expect(errors).toHaveLength(1);
+    });
+
     it('should ignore incompleteColumns when checking for errors', () => {
       const savedRef = jest.fn().mockReturnValue(['error 1']);
       const incompleteRef = jest.fn();
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts
index 56fbb8edef5b4..b650a2818b2d4 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts
@@ -169,6 +169,10 @@ export function insertNewColumn({
     if (field) {
       throw new Error(`Can't create operation ${op} with the provided field ${field.name}`);
     }
+    if (operationDefinition.input === 'managedReference') {
+      // TODO: need to create on the fly the new columns for Formula,
+      // like we do for fullReferences to show a seamless transition
+    }
     const possibleOperation = operationDefinition.getPossibleOperation();
     const isBucketed = Boolean(possibleOperation?.isBucketed);
     const addOperationFn = isBucketed ? addBucket : addMetric;
@@ -358,9 +362,9 @@ export function replaceColumn({
     tempLayer = resetIncomplete(tempLayer, columnId);
 
     if (previousDefinition.input === 'managedReference') {
-      // Every transition away from a managedReference resets it, we don't have a way to keep the state
+      // If the transition is incomplete, leave the managed state until it's finished.
       tempLayer = deleteColumn({ layer: tempLayer, columnId, indexPattern });
-      return insertNewColumn({
+      const hypotheticalLayer = insertNewColumn({
         layer: tempLayer,
         columnId,
         indexPattern,
@@ -368,6 +372,14 @@ export function replaceColumn({
         field,
         visualizationGroups,
       });
+      if (hypotheticalLayer.incompleteColumns && hypotheticalLayer.incompleteColumns[columnId]) {
+        return {
+          ...layer,
+          incompleteColumns: hypotheticalLayer.incompleteColumns,
+        };
+      } else {
+        return hypotheticalLayer;
+      }
     }
 
     if (operationDefinition.input === 'fullReference') {
@@ -859,7 +871,10 @@ function addBucket(
   visualizationGroups: VisualizationDimensionGroupConfig[],
   targetGroup?: string
 ): IndexPatternLayer {
-  const [buckets, metrics, references] = getExistingColumnGroups(layer);
+  const [buckets, metrics] = partition(
+    layer.columnOrder,
+    (colId) => layer.columns[colId].isBucketed
+  );
 
   const oldDateHistogramIndex = layer.columnOrder.findIndex(
     (columnId) => layer.columns[columnId].operationType === 'date_histogram'
@@ -873,12 +888,11 @@ function addBucket(
       addedColumnId,
       ...buckets.slice(oldDateHistogramIndex, buckets.length),
       ...metrics,
-      ...references,
     ];
   } else {
     // Insert the new bucket after existing buckets. Users will see the same data
     // they already had, with an extra level of detail.
-    updatedColumnOrder = [...buckets, addedColumnId, ...metrics, ...references];
+    updatedColumnOrder = [...buckets, addedColumnId, ...metrics];
   }
   updatedColumnOrder = reorderByGroups(
     visualizationGroups,
@@ -1169,8 +1183,20 @@ export function getErrorMessages(
         }
     >
   | undefined {
-  const errors = Object.entries(layer.columns)
+  const columns = Object.entries(layer.columns);
+  const visibleManagedReferences = columns.filter(
+    ([columnId, column]) =>
+      !isReferenced(layer, columnId) &&
+      operationDefinitionMap[column.operationType].input === 'managedReference'
+  );
+  const skippedColumns = visibleManagedReferences.flatMap(([columnId]) =>
+    getManagedColumnsFrom(columnId, layer.columns).map(([id]) => id)
+  );
+  const errors = columns
     .flatMap(([columnId, column]) => {
+      if (skippedColumns.includes(columnId)) {
+        return;
+      }
       const def = operationDefinitionMap[column.operationType];
       if (def.getErrorMessage) {
         return def.getErrorMessage(layer, columnId, indexPattern, operationDefinitionMap);
@@ -1218,6 +1244,25 @@ export function isReferenced(layer: IndexPatternLayer, columnId: string): boolea
   return allReferences.includes(columnId);
 }
 
+export function getReferencedColumnIds(layer: IndexPatternLayer, columnId: string): string[] {
+  const referencedIds: string[] = [];
+  function collect(id: string) {
+    const column = layer.columns[id];
+    if (column && 'references' in column) {
+      const columnReferences = column.references;
+      // only record references which have created columns yet
+      const existingReferences = columnReferences.filter((reference) =>
+        Boolean(layer.columns[reference])
+      );
+      referencedIds.push(...existingReferences);
+      existingReferences.forEach(collect);
+    }
+  }
+  collect(columnId);
+
+  return referencedIds;
+}
+
 export function isOperationAllowedAsReference({
   operationType,
   validation,
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/mocks.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/mocks.ts
index 4a2e065269063..2d7e70179fb3f 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/mocks.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/mocks.ts
@@ -40,3 +40,28 @@ export const createMockedFullReference = () => {
     getErrorMessage: jest.fn(),
   };
 };
+
+export const createMockedManagedReference = () => {
+  return {
+    input: 'managedReference',
+    displayName: 'Managed reference test',
+    type: 'managedReference' as OperationType,
+    selectionStyle: 'full',
+    buildColumn: jest.fn((args) => {
+      return {
+        label: 'Test reference',
+        isBucketed: false,
+        dataType: 'number',
+
+        operationType: 'testReference',
+        references: args.referenceIds,
+      };
+    }),
+    filterable: true,
+    isTransferable: jest.fn(),
+    toExpression: jest.fn().mockReturnValue([]),
+    getPossibleOperation: jest.fn().mockReturnValue({ dataType: 'number', isBucketed: false }),
+    getDefaultLabel: jest.fn().mockReturnValue('Default label'),
+    getErrorMessage: jest.fn(),
+  };
+};
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.ts
index 437d2af005961..fc70be257c8ad 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.ts
@@ -93,7 +93,7 @@ export function isDocumentOperation(type: string) {
   return documentOperations.has(type);
 }
 
-type OperationFieldTuple =
+export type OperationFieldTuple =
   | {
       type: 'field';
       operationType: OperationType;
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/types.ts b/x-pack/plugins/lens/public/indexpattern_datasource/types.ts
index 98dc767c44c7d..f24c39f810b21 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/types.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/types.ts
@@ -88,6 +88,8 @@ export interface IndexPatternPrivateState {
   isFirstExistenceFetch: boolean;
   existenceFetchFailed?: boolean;
   existenceFetchTimeout?: boolean;
+
+  isDimensionClosePrevented?: boolean;
 }
 
 export interface IndexPatternRef {
diff --git a/x-pack/plugins/lens/public/mocks.tsx b/x-pack/plugins/lens/public/mocks.tsx
index 473c170aef294..07935bb2f241b 100644
--- a/x-pack/plugins/lens/public/mocks.tsx
+++ b/x-pack/plugins/lens/public/mocks.tsx
@@ -166,6 +166,9 @@ export function mockDataPlugin(sessionIdSubject = new Subject<string>()) {
     nowProvider: {
       get: jest.fn(),
     },
+    fieldFormats: {
+      deserialize: jest.fn(),
+    },
   } as unknown) as DataPublicPluginStart;
 }
 
diff --git a/x-pack/plugins/lens/public/types.ts b/x-pack/plugins/lens/public/types.ts
index 6a816f8151687..7baba15f0fac6 100644
--- a/x-pack/plugins/lens/public/types.ts
+++ b/x-pack/plugins/lens/public/types.ts
@@ -199,6 +199,11 @@ export interface Datasource<T = unknown, P = unknown> {
     }
   ) => { dropTypes: DropType[]; nextLabel?: string } | undefined;
   onDrop: (props: DatasourceDimensionDropHandlerProps<T>) => false | true | { deleted: string };
+  /**
+   * The datasource is allowed to cancel a close event on the dimension editor,
+   * mainly used for formulas
+   */
+  canCloseDimensionEditor?: (state: T) => boolean;
   getCustomWorkspaceRenderer?: (
     state: T,
     dragging: DraggingIdentifier
@@ -301,11 +306,15 @@ export type DatasourceDimensionEditorProps<T = unknown> = DatasourceDimensionPro
   // Not a StateSetter because we have this unique use case of determining valid columns
   setState: (
     newState: Parameters<StateSetter<T>>[0],
-    publishToVisualization?: { shouldReplaceDimension?: boolean; shouldRemoveDimension?: boolean }
+    publishToVisualization?: {
+      isDimensionComplete?: boolean;
+    }
   ) => void;
   core: Pick<CoreSetup, 'http' | 'notifications' | 'uiSettings'>;
   dateRange: DateRange;
   dimensionGroups: VisualizationDimensionGroupConfig[];
+  toggleFullscreen: () => void;
+  isFullscreen: boolean;
 };
 
 export type DatasourceDimensionTriggerProps<T> = DatasourceDimensionProps<T>;
diff --git a/x-pack/plugins/lens/server/usage/schema.ts b/x-pack/plugins/lens/server/usage/schema.ts
index ab3945a0162a6..c3608176717c5 100644
--- a/x-pack/plugins/lens/server/usage/schema.ts
+++ b/x-pack/plugins/lens/server/usage/schema.ts
@@ -14,6 +14,12 @@ const eventsSchema: MakeSchemaFrom<LensUsage['events_30_days']> = {
     type: 'long',
     _meta: { description: 'Number of times the user opened one of the in-product help popovers.' },
   },
+  toggle_fullscreen_formula: {
+    type: 'long',
+    _meta: {
+      description: 'Number of times the user toggled fullscreen mode on formula.',
+    },
+  },
   indexpattern_field_info_click: { type: 'long' },
   loaded: { type: 'long' },
   app_filters_updated: { type: 'long' },
@@ -162,6 +168,10 @@ const eventsSchema: MakeSchemaFrom<LensUsage['events_30_days']> = {
     type: 'long',
     _meta: { description: 'Number of times the moving average function was selected' },
   },
+  indexpattern_dimension_operation_formula: {
+    type: 'long',
+    _meta: { description: 'Number of times the formula function was selected' },
+  },
 };
 
 const suggestionEventsSchema: MakeSchemaFrom<LensUsage['suggestion_events_30_days']> = {
@@ -183,6 +193,12 @@ const savedSchema: MakeSchemaFrom<LensUsage['saved_overall']> = {
   lnsDatatable: { type: 'long' },
   lnsPie: { type: 'long' },
   lnsMetric: { type: 'long' },
+  formula: {
+    type: 'long',
+    _meta: {
+      description: 'Number of saved lens visualizations which are using at least one formula',
+    },
+  },
 };
 
 export const lensUsageSchema: MakeSchemaFrom<LensUsage> = {
diff --git a/x-pack/plugins/lens/server/usage/visualization_counts.ts b/x-pack/plugins/lens/server/usage/visualization_counts.ts
index 3b9bb99caf5b8..f0c48fb1152e8 100644
--- a/x-pack/plugins/lens/server/usage/visualization_counts.ts
+++ b/x-pack/plugins/lens/server/usage/visualization_counts.ts
@@ -43,6 +43,31 @@ export async function getVisualizationCounts(
                 size: 100,
               },
             },
+            usesFormula: {
+              filter: {
+                match: {
+                  operation_type: 'formula',
+                },
+              },
+            },
+          },
+        },
+      },
+      runtime_mappings: {
+        operation_type: {
+          type: 'keyword',
+          script: {
+            lang: 'painless',
+            source: `try {
+              if(doc['lens.state'].size() == 0) return;
+              HashMap layers = params['_source'].get('lens').get('state').get('datasourceStates').get('indexpattern').get('layers');
+              for(layerId in layers.keySet()) {
+                HashMap columns = layers.get(layerId).get('columns');
+                for(columnId in columns.keySet()) {
+                  emit(columns.get(columnId).get('operationType'))
+                }
+              }
+            } catch(Exception e) {}`,
           },
         },
       },
@@ -56,16 +81,19 @@ export async function getVisualizationCounts(
   // eslint-disable-next-line @typescript-eslint/no-explicit-any
   function bucketsToObject(arg: any) {
     const obj: Record<string, number> = {};
-    arg.buckets.forEach((bucket: { key: string; doc_count: number }) => {
+    arg.byType.buckets.forEach((bucket: { key: string; doc_count: number }) => {
       obj[bucket.key] = bucket.doc_count + (obj[bucket.key] ?? 0);
     });
+    if (arg.usesFormula.doc_count > 0) {
+      obj.formula = arg.usesFormula.doc_count;
+    }
     return obj;
   }
 
   return {
-    saved_overall: bucketsToObject(buckets.overall.byType),
-    saved_30_days: bucketsToObject(buckets.last30.byType),
-    saved_90_days: bucketsToObject(buckets.last90.byType),
+    saved_overall: bucketsToObject(buckets.overall),
+    saved_30_days: bucketsToObject(buckets.last30),
+    saved_90_days: bucketsToObject(buckets.last90),
     saved_overall_total: buckets.overall.doc_count,
     saved_30_days_total: buckets.last30.doc_count,
     saved_90_days_total: buckets.last90.doc_count,
diff --git a/x-pack/plugins/ml/common/types/results.ts b/x-pack/plugins/ml/common/types/results.ts
index 83de62d51671e..fa40cefcaed48 100644
--- a/x-pack/plugins/ml/common/types/results.ts
+++ b/x-pack/plugins/ml/common/types/results.ts
@@ -5,6 +5,28 @@
  * 2.0.
  */
 
+import { estypes } from '@elastic/elasticsearch';
+
 export interface GetStoppedPartitionResult {
   jobs: string[] | Record<string, string[]>;
 }
+export interface GetDatafeedResultsChartDataResult {
+  bucketResults: number[][];
+  datafeedResults: number[][];
+}
+
+export interface DatafeedResultsChartDataParams {
+  jobId: string;
+  start: number;
+  end: number;
+}
+
+export const defaultSearchQuery: estypes.QueryDslQueryContainer = {
+  bool: {
+    must: [
+      {
+        match_all: {},
+      },
+    ],
+  },
+};
diff --git a/x-pack/plugins/ml/kibana.json b/x-pack/plugins/ml/kibana.json
index f34172765e1dd..e3bcf307e6f00 100644
--- a/x-pack/plugins/ml/kibana.json
+++ b/x-pack/plugins/ml/kibana.json
@@ -39,7 +39,8 @@
     "dashboard",
     "savedObjects",
     "home",
-    "maps"
+    "maps",
+    "usageCollection"
   ],
   "extraPublicDirs": [
     "common"
diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx
index f16a7c561ac5d..8be513f372e56 100644
--- a/x-pack/plugins/ml/public/application/app.tsx
+++ b/x-pack/plugins/ml/public/application/app.tsx
@@ -87,17 +87,22 @@ const App: FC<AppProps> = ({ coreStart, deps, appMountParams }) => {
   };
 
   const I18nContext = coreStart.i18n.Context;
+  const ApplicationUsageTrackingProvider =
+    deps.usageCollection?.components.ApplicationUsageTrackingProvider ?? React.Fragment;
+
   return (
     /** RedirectAppLinks intercepts all <a> tags to use navigateToUrl
      * avoiding full page reload **/
     <RedirectAppLinks application={coreStart.application}>
-      <I18nContext>
-        <KibanaContextProvider
-          services={{ ...services, mlServices: getMlGlobalServices(coreStart.http) }}
-        >
-          <MlRouter pageDeps={pageDeps} />
-        </KibanaContextProvider>
-      </I18nContext>
+      <ApplicationUsageTrackingProvider>
+        <I18nContext>
+          <KibanaContextProvider
+            services={{ ...services, mlServices: getMlGlobalServices(coreStart.http) }}
+          >
+            <MlRouter pageDeps={pageDeps} />
+          </KibanaContextProvider>
+        </I18nContext>
+      </ApplicationUsageTrackingProvider>
     </RedirectAppLinks>
   );
 };
diff --git a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js
index 472bde00e649a..afed7e79ff757 100644
--- a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js
+++ b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js
@@ -18,14 +18,13 @@ import React, { Component, Fragment, useContext } from 'react';
 import memoizeOne from 'memoize-one';
 import {
   EuiBadge,
-  EuiButtonIcon,
+  EuiButtonEmpty,
   EuiCallOut,
   EuiFlexGroup,
   EuiFlexItem,
   EuiInMemoryTable,
   EuiLink,
   EuiLoadingSpinner,
-  EuiToolTip,
 } from '@elastic/eui';
 import { i18n } from '@kbn/i18n';
 import { FormattedMessage } from '@kbn/i18n/react';
@@ -52,6 +51,7 @@ import { ML_APP_URL_GENERATOR, ML_PAGES } from '../../../../../common/constants/
 import { PLUGIN_ID } from '../../../../../common/constants/app';
 import { timeFormatter } from '../../../../../common/util/date_utils';
 import { MlAnnotationUpdatesContext } from '../../../contexts/ml/ml_annotation_updates_context';
+import { DatafeedModal } from '../../../jobs/jobs_list/components/datafeed_modal';
 
 const CURRENT_SERIES = 'current_series';
 /**
@@ -79,6 +79,8 @@ class AnnotationsTableUI extends Component {
         this.props.jobs[0] !== undefined
           ? this.props.jobs[0].job_id
           : undefined,
+      datafeedModalVisible: false,
+      datafeedEnd: null,
     };
     this.sorting = {
       sort: { field: 'timestamp', direction: 'asc' },
@@ -463,28 +465,62 @@ class AnnotationsTableUI extends Component {
         // find the original annotation because the table might not show everything
         const annotationId = annotation._id;
         const originalAnnotation = annotations.find((d) => d._id === annotationId);
-        const editAnnotationsTooltipText = (
+        const editAnnotationsText = (
           <FormattedMessage
             id="xpack.ml.annotationsTable.editAnnotationsTooltip"
             defaultMessage="Edit annotation"
           />
         );
-        const editAnnotationsTooltipAriaLabelText = i18n.translate(
+        const editAnnotationsAriaLabelText = i18n.translate(
           'xpack.ml.annotationsTable.editAnnotationsTooltipAriaLabel',
           { defaultMessage: 'Edit annotation' }
         );
         return (
-          <EuiToolTip position="bottom" content={editAnnotationsTooltipText}>
-            <EuiButtonIcon
-              onClick={() => annotationUpdatesService.setValue(originalAnnotation ?? annotation)}
-              iconType="pencil"
-              aria-label={editAnnotationsTooltipAriaLabelText}
-            />
-          </EuiToolTip>
+          <EuiButtonEmpty
+            size="xs"
+            aria-label={editAnnotationsAriaLabelText}
+            iconType="pencil"
+            onClick={() => annotationUpdatesService.setValue(originalAnnotation ?? annotation)}
+          >
+            {editAnnotationsText}
+          </EuiButtonEmpty>
         );
       },
     });
 
+    if (this.state.jobId && this.props.jobs[0].analysis_config.bucket_span) {
+      // add datafeed modal action
+      actions.push({
+        render: (annotation) => {
+          const viewDataFeedText = (
+            <FormattedMessage
+              id="xpack.ml.annotationsTable.viewDatafeedTooltip"
+              defaultMessage="View datafeed"
+            />
+          );
+          const viewDataFeedTooltipAriaLabelText = i18n.translate(
+            'xpack.ml.annotationsTable.viewDatafeedTooltipAriaLabel',
+            { defaultMessage: 'View datafeed' }
+          );
+          return (
+            <EuiButtonEmpty
+              size="xs"
+              aria-label={viewDataFeedTooltipAriaLabelText}
+              iconType="visAreaStacked"
+              onClick={() =>
+                this.setState({
+                  datafeedModalVisible: true,
+                  datafeedEnd: annotation.end_timestamp,
+                })
+              }
+            >
+              {viewDataFeedText}
+            </EuiButtonEmpty>
+          );
+        },
+      });
+    }
+
     if (isSingleMetricViewerLinkVisible) {
       actions.push({
         render: (annotation) => {
@@ -510,14 +546,15 @@ class AnnotationsTableUI extends Component {
               );
 
           return (
-            <EuiToolTip position="bottom" content={openInSingleMetricViewerTooltipText}>
-              <EuiButtonIcon
-                onClick={() => this.openSingleMetricView(annotation)}
-                disabled={!isDrillDownAvailable}
-                iconType="visLine"
-                aria-label={openInSingleMetricViewerAriaLabelText}
-              />
-            </EuiToolTip>
+            <EuiButtonEmpty
+              size="xs"
+              disabled={!isDrillDownAvailable}
+              aria-label={openInSingleMetricViewerAriaLabelText}
+              iconType="visLine"
+              onClick={() => this.openSingleMetricView(annotation)}
+            >
+              {openInSingleMetricViewerTooltipText}
+            </EuiButtonEmpty>
           );
         },
       });
@@ -690,6 +727,19 @@ class AnnotationsTableUI extends Component {
           search={search}
           rowProps={getRowProps}
         />
+        {this.state.jobId && this.state.datafeedModalVisible && this.state.datafeedEnd ? (
+          <DatafeedModal
+            onClose={() => {
+              this.setState({
+                datafeedModalVisible: false,
+              });
+            }}
+            end={this.state.datafeedEnd}
+            timefield={this.props.jobs[0].data_description.time_field}
+            jobId={this.state.jobId}
+            bucketSpan={this.props.jobs[0].analysis_config.bucket_span}
+          />
+        ) : null}
       </Fragment>
     );
   }
diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/confusion_matrix_help_popover.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/confusion_matrix_help_popover.tsx
new file mode 100644
index 0000000000000..34fad4d8acb45
--- /dev/null
+++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/confusion_matrix_help_popover.tsx
@@ -0,0 +1,61 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { useState } from 'react';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import {
+  HelpPopover,
+  HelpPopoverButton,
+} from '../../../../../components/help_popover/help_popover';
+
+export const MulticlassConfusionMatrixHelpPopover = () => {
+  const [isPopoverOpen, setIsPopoverOpen] = useState(false);
+
+  return (
+    <HelpPopover
+      anchorPosition="upCenter"
+      button={
+        <HelpPopoverButton
+          onClick={() => {
+            setIsPopoverOpen(!isPopoverOpen);
+          }}
+        />
+      }
+      closePopover={() => setIsPopoverOpen(false)}
+      isOpen={isPopoverOpen}
+      title={i18n.translate('xpack.ml.dataframe.analytics.confusionMatrixPopoverTitle', {
+        defaultMessage: 'Normalized confusion matrix',
+      })}
+    >
+      <p>
+        <FormattedMessage
+          id="xpack.ml.dataframe.analytics.confusionMatrixBasicExplanation"
+          defaultMessage="The multiclass confusion matrix provides a summary of the performance of the classification analysis. It contains the proportion of the data points that the analysis classified correctly with their actual class as well as the proportion of the misclassified data points."
+        />
+      </p>
+      <p>
+        <FormattedMessage
+          id="xpack.ml.dataframe.analytics.confusionMatrixAxisExplanation"
+          defaultMessage="The matrix contains the actual labels on the left side while the predicted labels are on the top. The proportion of correct and incorrect predictions is broken down for each class. This enables you to examine how the classification analysis confused the different classes while it made its predictions. If you want to see the exact number of occurrences, select a cell in the matrix and click the appearing icon."
+        />
+      </p>
+      <p>
+        <FormattedMessage
+          id="xpack.ml.dataframe.analytics.confusionMatrixShadeExplanation"
+          defaultMessage="As the number of classes in the classification analysis increases, the confusion matrix also increases in complexity. For an easier overview, darker cells indicate higher percentage of the predictions."
+        />
+      </p>
+      <p>
+        <FormattedMessage
+          id="xpack.ml.dataframe.analytics.confusionMatrixColumnExplanation"
+          defaultMessage="The Columns selector enables you to toggle between showing or hiding some of the columns or all of them."
+        />
+      </p>
+    </HelpPopover>
+  );
+};
diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx
index f37be6f6f0eb0..bc1c9dbed1dcc 100644
--- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx
+++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx
@@ -50,6 +50,7 @@ import {
 import { isTrainingFilter } from './is_training_filter';
 import { useRocCurve } from './use_roc_curve';
 import { useConfusionMatrix } from './use_confusion_matrix';
+import { MulticlassConfusionMatrixHelpPopover } from './confusion_matrix_help_popover';
 
 export interface EvaluatePanelProps {
   jobConfig: DataFrameAnalyticsConfig;
@@ -288,21 +289,12 @@ export const EvaluatePanel: FC<EvaluatePanelProps> = ({ jobConfig, jobStatus, se
                 {errorConfusionMatrix !== null && <ErrorCallout error={errorConfusionMatrix} />}
                 {errorConfusionMatrix === null && (
                   <>
-                    <EuiFlexGroup gutterSize="none">
+                    <EuiFlexGroup gutterSize="none" alignItems="center">
                       <EuiTitle size="xxs">
                         <span>{getHelpText(dataSubsetTitle)}</span>
                       </EuiTitle>
                       <EuiFlexItem grow={false}>
-                        <EuiIconTip
-                          anchorClassName="mlDataFrameAnalyticsClassificationInfoTooltip"
-                          content={i18n.translate(
-                            'xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixTooltip',
-                            {
-                              defaultMessage:
-                                'The multi-class confusion matrix contains the number of occurrences where the analysis classified data points correctly with their actual class as well as the number of occurrences where it misclassified them with another class',
-                            }
-                          )}
-                        />
+                        <MulticlassConfusionMatrixHelpPopover />
                       </EuiFlexItem>
                     </EuiFlexGroup>
                     {/* BEGIN TABLE ELEMENTS */}
diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/constants.ts b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/constants.ts
new file mode 100644
index 0000000000000..71f3795518bc9
--- /dev/null
+++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/constants.ts
@@ -0,0 +1,41 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { ChartSizeArray } from '@elastic/charts';
+import { i18n } from '@kbn/i18n';
+
+export const CHART_DIRECTION = {
+  FORWARD: 'forward',
+  BACK: 'back',
+} as const;
+export type ChartDirectionType = typeof CHART_DIRECTION[keyof typeof CHART_DIRECTION];
+
+// [width, height]
+export const CHART_SIZE: ChartSizeArray = ['100%', 300];
+
+export const TAB_IDS = {
+  CHART: 'chart',
+  MESSAGES: 'messages',
+} as const;
+export type TabIdsType = typeof TAB_IDS[keyof typeof TAB_IDS];
+
+export const tabs = [
+  {
+    id: TAB_IDS.CHART,
+    name: i18n.translate('xpack.ml.jobsList.datafeedModal.chartTabName', {
+      defaultMessage: 'Chart',
+    }),
+    disabled: false,
+  },
+  {
+    id: TAB_IDS.MESSAGES,
+    name: i18n.translate('xpack.ml.jobsList.datafeedModal.messagesTabName', {
+      defaultMessage: 'Messages',
+    }),
+    disabled: false,
+  },
+];
diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/datafeed_modal.tsx b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/datafeed_modal.tsx
new file mode 100644
index 0000000000000..cf547a49cac4c
--- /dev/null
+++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/datafeed_modal.tsx
@@ -0,0 +1,362 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { i18n } from '@kbn/i18n';
+import moment from 'moment';
+import {
+  EuiButtonEmpty,
+  EuiDatePicker,
+  EuiFlexGroup,
+  EuiFlexItem,
+  EuiLoadingChart,
+  EuiModal,
+  EuiModalHeader,
+  EuiModalBody,
+  EuiSelect,
+  EuiSpacer,
+  EuiTabs,
+  EuiTab,
+  EuiToolTip,
+} from '@elastic/eui';
+import {
+  Axis,
+  Chart,
+  CurveType,
+  LineSeries,
+  Position,
+  ScaleType,
+  Settings,
+  timeFormatter,
+} from '@elastic/charts';
+
+import { DATAFEED_STATE } from '../../../../../../common/constants/states';
+import { CombinedJobWithStats } from '../../../../../../common/types/anomaly_detection_jobs';
+import { useToastNotificationService } from '../../../../services/toast_notification_service';
+import { useMlApiContext } from '../../../../contexts/kibana';
+import { useCurrentEuiTheme } from '../../../../components/color_range_legend';
+import { JobMessagesPane } from '../job_details/job_messages_pane';
+import { EditQueryDelay } from './edit_query_delay';
+import { getIntervalOptions } from './get_interval_options';
+import {
+  CHART_DIRECTION,
+  ChartDirectionType,
+  CHART_SIZE,
+  tabs,
+  TAB_IDS,
+  TabIdsType,
+} from './constants';
+import { loadFullJob } from '../utils';
+
+const dateFormatter = timeFormatter('MM-DD HH:mm');
+
+interface DatafeedModalProps {
+  jobId: string;
+  end: number;
+  onClose: (deletionApproved?: boolean) => void;
+}
+
+export const DatafeedModal: FC<DatafeedModalProps> = ({ jobId, end, onClose }) => {
+  const [data, setData] = useState<{
+    datafeedConfig: CombinedJobWithStats['datafeed_config'] | undefined;
+    bucketSpan: string | undefined;
+    isInitialized: boolean;
+  }>({ datafeedConfig: undefined, bucketSpan: undefined, isInitialized: false });
+  const [endDate, setEndDate] = useState<any>(moment(end));
+  const [interval, setInterval] = useState<string | undefined>();
+  const [selectedTabId, setSelectedTabId] = useState<TabIdsType>(TAB_IDS.CHART);
+  const [isLoadingChartData, setIsLoadingChartData] = useState<boolean>(false);
+  const [bucketData, setBucketData] = useState<number[][]>([]);
+  const [sourceData, setSourceData] = useState<number[][]>([]);
+
+  const {
+    results: { getDatafeedResultChartData },
+  } = useMlApiContext();
+  const { displayErrorToast } = useToastNotificationService();
+  const { euiTheme } = useCurrentEuiTheme();
+
+  const onSelectedTabChanged = (id: TabIdsType) => {
+    setSelectedTabId(id);
+  };
+
+  const renderTabs = useCallback(
+    () =>
+      tabs.map((tab, index) => (
+        <EuiTab
+          onClick={() => onSelectedTabChanged(tab.id)}
+          isSelected={tab.id === selectedTabId}
+          disabled={tab.disabled}
+          key={index}
+        >
+          {tab.name}
+        </EuiTab>
+      )),
+    [selectedTabId]
+  );
+
+  const handleChange = (date: moment.Moment) => setEndDate(date);
+
+  const handleEndDateChange = (direction: ChartDirectionType) => {
+    if (interval === undefined) return;
+
+    const newEndDate = endDate.clone();
+    const [count, type] = interval.split(' ');
+
+    if (direction === CHART_DIRECTION.FORWARD) {
+      newEndDate.add(Number(count), type);
+    } else {
+      newEndDate.subtract(Number(count), type);
+    }
+    setEndDate(newEndDate);
+  };
+
+  const getChartData = useCallback(async () => {
+    if (interval === undefined) return;
+
+    const endTimestamp = moment(endDate).valueOf();
+    const [count, type] = interval.split(' ');
+    const startMoment = endDate.clone().subtract(Number(count), type);
+    const startTimestamp = moment(startMoment).valueOf();
+
+    try {
+      const chartData = await getDatafeedResultChartData(jobId, startTimestamp, endTimestamp);
+
+      setSourceData(chartData.datafeedResults);
+      setBucketData(chartData.bucketResults);
+    } catch (error) {
+      const title = i18n.translate('xpack.ml.jobsList.datafeedModal.errorToastTitle', {
+        defaultMessage: 'Error fetching data',
+      });
+      displayErrorToast(error, title);
+    }
+    setIsLoadingChartData(false);
+  }, [endDate, interval]);
+
+  const getJobData = async () => {
+    try {
+      const job: CombinedJobWithStats = await loadFullJob(jobId);
+      setData({
+        datafeedConfig: job.datafeed_config,
+        bucketSpan: job.analysis_config.bucket_span,
+        isInitialized: true,
+      });
+      const intervalOptions = getIntervalOptions(job.analysis_config.bucket_span);
+      const initialInterval = intervalOptions.length
+        ? intervalOptions[intervalOptions.length - 1]
+        : undefined;
+      setInterval(initialInterval?.value || '72 hours');
+    } catch (error) {
+      displayErrorToast(error);
+    }
+  };
+
+  useEffect(function loadJobWithDatafeed() {
+    getJobData();
+  }, []);
+
+  useEffect(
+    function loadChartData() {
+      if (interval !== undefined) {
+        setIsLoadingChartData(true);
+        getChartData();
+      }
+    },
+    [endDate, interval]
+  );
+
+  const { datafeedConfig, bucketSpan, isInitialized } = data;
+
+  const intervalOptions = useMemo(() => {
+    if (bucketSpan === undefined) return [];
+    return getIntervalOptions(bucketSpan);
+  }, [bucketSpan]);
+
+  return (
+    <EuiModal
+      onClose={onClose.bind(null, false)}
+      className="mlDatafeedModal"
+      style={{ height: '600px', minWidth: '800px' }}
+    >
+      <EuiModalHeader>
+        <EuiFlexGroup alignItems="center" justifyContent="spaceBetween" gutterSize="xl">
+          <EuiFlexItem grow={false}>
+            <FormattedMessage
+              id="xpack.ml.jobsList.datafeedModal.header"
+              defaultMessage="{jobId}"
+              values={{
+                jobId,
+              }}
+            />
+          </EuiFlexItem>
+          <EuiFlexItem grow={false}>
+            <EuiDatePicker
+              aria-label={i18n.translate('xpack.ml.jobsList.datafeedModal.chartIntervalEndTime', {
+                defaultMessage: 'Chart interval end time',
+              })}
+              showTimeSelect
+              selected={endDate}
+              onChange={handleChange}
+              popoverPlacement="left-start"
+            />
+          </EuiFlexItem>
+        </EuiFlexGroup>
+      </EuiModalHeader>
+
+      <EuiModalBody>
+        <EuiTabs size="s">{renderTabs()}</EuiTabs>
+        <EuiSpacer size="m" />
+        {isLoadingChartData || isInitialized === false ? <EuiLoadingChart size="l" /> : null}
+        {!isLoadingChartData &&
+          isInitialized &&
+          selectedTabId === TAB_IDS.CHART &&
+          datafeedConfig !== undefined &&
+          bucketSpan && (
+            <EuiFlexGroup direction="column">
+              <EuiFlexItem grow={false}>
+                <EuiFlexGroup justifyContent="spaceBetween">
+                  <EuiFlexItem grow={false}>
+                    <EuiSelect
+                      options={intervalOptions}
+                      value={interval}
+                      onChange={(e) => setInterval(e.target.value)}
+                      aria-label={i18n.translate(
+                        'xpack.ml.jobsList.datafeedModal.intervalSelection',
+                        {
+                          defaultMessage: 'Datafeed modal chart interval selection',
+                        }
+                      )}
+                    />
+                  </EuiFlexItem>
+                  <EuiFlexItem grow={false}>
+                    <EditQueryDelay
+                      datafeedId={datafeedConfig.datafeed_id}
+                      queryDelay={datafeedConfig.query_delay}
+                      isEnabled={datafeedConfig.state === DATAFEED_STATE.STOPPED}
+                    />
+                  </EuiFlexItem>
+                </EuiFlexGroup>
+              </EuiFlexItem>
+              <EuiFlexItem>
+                <EuiFlexGroup gutterSize="none" alignItems="center">
+                  <EuiFlexItem grow={false}>
+                    <EuiToolTip
+                      content={
+                        <FormattedMessage
+                          id="xpack.ml.jobsList.datafeedModal.chartLeftArrowTooltip"
+                          defaultMessage="Previous time window"
+                        />
+                      }
+                    >
+                      <EuiButtonEmpty
+                        aria-label={i18n.translate(
+                          'xpack.ml.jobsList.datafeedModal.chartIntervalLeftArrow',
+                          {
+                            defaultMessage: 'Previous time window',
+                          }
+                        )}
+                        color="primary"
+                        size="l"
+                        onClick={() => {
+                          handleEndDateChange(CHART_DIRECTION.BACK);
+                        }}
+                        iconType="arrowLeft"
+                      />
+                    </EuiToolTip>
+                  </EuiFlexItem>
+                  <EuiFlexItem>
+                    <Chart size={CHART_SIZE}>
+                      <Settings
+                        showLegend
+                        legendPosition={Position.Bottom}
+                        theme={{
+                          lineSeriesStyle: {
+                            point: {
+                              visible: false,
+                            },
+                          },
+                        }}
+                      />
+                      <Axis
+                        id="bottom"
+                        position={Position.Bottom}
+                        showOverlappingTicks
+                        tickFormat={dateFormatter}
+                        title={i18n.translate('xpack.ml.jobsList.datafeedModal.xAxisTitle', {
+                          defaultMessage: 'Bucket span ({bucketSpan})',
+                          values: { bucketSpan },
+                        })}
+                      />
+                      <Axis
+                        id="left"
+                        title={i18n.translate('xpack.ml.jobsList.datafeedModal.yAxisTitle', {
+                          defaultMessage: 'Count',
+                        })}
+                        position={Position.Left}
+                      />
+                      <LineSeries
+                        color={euiTheme.euiColorPrimary}
+                        id={i18n.translate('xpack.ml.jobsList.datafeedModal.sourceSeriesId', {
+                          defaultMessage: 'Source indices',
+                        })}
+                        xScaleType={ScaleType.Time}
+                        yScaleType={ScaleType.Linear}
+                        xAccessor={0}
+                        yAccessors={[1]}
+                        data={sourceData}
+                        curve={CurveType.LINEAR}
+                      />
+                      <LineSeries
+                        color={euiTheme.euiColorAccentText}
+                        id={i18n.translate('xpack.ml.jobsList.datafeedModal.bucketSeriesId', {
+                          defaultMessage: 'Job results',
+                        })}
+                        xScaleType={ScaleType.Time}
+                        yScaleType={ScaleType.Linear}
+                        xAccessor={0}
+                        yAccessors={[1]}
+                        data={bucketData}
+                        curve={CurveType.LINEAR}
+                      />
+                    </Chart>
+                  </EuiFlexItem>
+                  <EuiFlexItem grow={false}>
+                    <EuiToolTip
+                      content={
+                        <FormattedMessage
+                          id="xpack.ml.jobsList.datafeedModal.chartRightArrowTooltip"
+                          defaultMessage="Next time window"
+                        />
+                      }
+                    >
+                      <EuiButtonEmpty
+                        aria-label={i18n.translate(
+                          'xpack.ml.jobsList.datafeedModal.chartIntervalRightArrow',
+                          {
+                            defaultMessage: 'Next time window',
+                          }
+                        )}
+                        color="primary"
+                        size="l"
+                        onClick={() => {
+                          handleEndDateChange(CHART_DIRECTION.FORWARD);
+                        }}
+                        iconType="arrowRight"
+                      />
+                    </EuiToolTip>
+                  </EuiFlexItem>
+                </EuiFlexGroup>
+              </EuiFlexItem>
+            </EuiFlexGroup>
+          )}
+        {!isLoadingChartData && selectedTabId === TAB_IDS.MESSAGES ? (
+          <JobMessagesPane jobId={jobId} />
+        ) : null}
+      </EuiModalBody>
+    </EuiModal>
+  );
+};
diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/edit_query_delay.tsx b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/edit_query_delay.tsx
new file mode 100644
index 0000000000000..5a25781a505d1
--- /dev/null
+++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/edit_query_delay.tsx
@@ -0,0 +1,142 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { FC, useCallback, useState } from 'react';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { i18n } from '@kbn/i18n';
+import {
+  EuiButtonEmpty,
+  EuiFieldText,
+  EuiFlexGroup,
+  EuiFlexItem,
+  EuiFormRow,
+  EuiToolTip,
+} from '@elastic/eui';
+
+import { useMlApiContext } from '../../../../contexts/kibana';
+import { useToastNotificationService } from '../../../../services/toast_notification_service';
+import { Datafeed } from '../../../../../../common/types/anomaly_detection_jobs';
+
+const tooltipContent = i18n.translate(
+  'xpack.ml.jobsList.datafeedModal.editQueryDelay.tooltipContent',
+  {
+    defaultMessage: 'Cannot update query delay when datafeed is running.',
+  }
+);
+
+export const EditQueryDelay: FC<{
+  datafeedId: Datafeed['datafeed_id'];
+  queryDelay: Datafeed['query_delay'];
+  isEnabled: boolean;
+}> = ({ datafeedId, queryDelay, isEnabled }) => {
+  const [newQueryDelay, setNewQueryDelay] = useState<string | undefined>();
+  const [isEditing, setIsEditing] = useState<boolean>(false);
+  const { updateDatafeed } = useMlApiContext();
+  const { displaySuccessToast, displayErrorToast } = useToastNotificationService();
+
+  const updateQueryDelay = useCallback(async () => {
+    try {
+      await updateDatafeed({
+        datafeedId,
+        datafeedConfig: { query_delay: newQueryDelay },
+      });
+      displaySuccessToast(
+        i18n.translate(
+          'xpack.ml.jobsList.datafeedModal.editQueryDelay.changesSavedNotificationMessage',
+          {
+            defaultMessage: 'Changes to query delay for {datafeedId} saved',
+            values: {
+              datafeedId,
+            },
+          }
+        )
+      );
+    } catch (error) {
+      displayErrorToast(
+        error,
+        i18n.translate(
+          'xpack.ml.jobsList.datafeedModal.editQueryDelay.changesNotSavedNotificationMessage',
+          {
+            defaultMessage: 'Could not save changes to query delay for {datafeedId}',
+            values: {
+              datafeedId,
+            },
+          }
+        )
+      );
+    }
+    setIsEditing(false);
+  }, [datafeedId, newQueryDelay]);
+
+  const editButton = (
+    <EuiButtonEmpty
+      color="primary"
+      size="xs"
+      isDisabled={isEnabled === false}
+      onClick={() => {
+        setIsEditing(true);
+      }}
+      iconType="pencil"
+    >
+      <FormattedMessage
+        id="xpack.ml.jobsList.datafeedModal.queryDelayLinkLabel"
+        defaultMessage="Query delay: {queryDelay}"
+        values={{ queryDelay: newQueryDelay || queryDelay }}
+      />
+    </EuiButtonEmpty>
+  );
+
+  const editButtonWithTooltip = <EuiToolTip content={tooltipContent}>{editButton}</EuiToolTip>;
+
+  return (
+    <>
+      {isEditing === false ? (isEnabled === false ? editButtonWithTooltip : editButton) : null}
+      {isEditing === true ? (
+        <EuiFormRow
+          label={
+            <FormattedMessage
+              id="xpack.ml.jobsList.datafeedModal.queryDelayLabel"
+              defaultMessage="Query delay"
+            />
+          }
+        >
+          <EuiFlexGroup gutterSize="none" alignItems="center">
+            <EuiFlexItem grow={false}>
+              <EuiFieldText
+                value={newQueryDelay || queryDelay}
+                placeholder={queryDelay}
+                onChange={(e) => {
+                  setNewQueryDelay(e.target.value);
+                }}
+              />
+            </EuiFlexItem>
+            <EuiFlexItem grow={false}>
+              <EuiFlexGroup gutterSize="none" direction="column">
+                <EuiFlexItem grow={false}>
+                  <EuiButtonEmpty color="primary" size="xs" onClick={updateQueryDelay}>
+                    <FormattedMessage
+                      id="xpack.ml.jobsList.datafeedModal.applyQueryDelayLabel"
+                      defaultMessage="Apply"
+                    />
+                  </EuiButtonEmpty>
+                </EuiFlexItem>
+                <EuiFlexItem grow={false}>
+                  <EuiButtonEmpty color="text" size="xs" onClick={() => setIsEditing(false)}>
+                    <FormattedMessage
+                      id="xpack.ml.jobsList.datafeedModal.cancelQueryDelayUpdateLabel"
+                      defaultMessage="Cancel"
+                    />
+                  </EuiButtonEmpty>
+                </EuiFlexItem>
+              </EuiFlexGroup>
+            </EuiFlexItem>
+          </EuiFlexGroup>
+        </EuiFormRow>
+      ) : null}
+    </>
+  );
+};
diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/get_interval_options.ts b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/get_interval_options.ts
new file mode 100644
index 0000000000000..cc9431549c79c
--- /dev/null
+++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/get_interval_options.ts
@@ -0,0 +1,118 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { i18n } from '@kbn/i18n';
+
+export const getIntervalOptions = (bucketSpan: string) => {
+  const unitMatch = bucketSpan.match(/[d | h| m | s]/g)!;
+  const unit = unitMatch[0];
+  const count = Number(bucketSpan.replace(/[^0-9]/g, ''));
+
+  const intervalOptions = [];
+
+  if (['s', 'ms', 'micros', 'nanos'].includes(unit)) {
+    intervalOptions.push(
+      {
+        value: '1 hour',
+        text: i18n.translate('xpack.ml.jobsList.datafeedModal.1hourOption', {
+          defaultMessage: '{count} hour',
+          values: { count: 1 },
+        }),
+      },
+      {
+        value: '2 hours',
+        text: i18n.translate('xpack.ml.jobsList.datafeedModal.2hourOption', {
+          defaultMessage: '{count} hours',
+          values: { count: 2 },
+        }),
+      }
+    );
+  }
+
+  if ((unit === 'm' && count <= 4) || unit === 'h') {
+    intervalOptions.push(
+      {
+        value: '3 hours',
+        text: i18n.translate('xpack.ml.jobsList.datafeedModal.3hourOption', {
+          defaultMessage: '{count} hours',
+          values: { count: 3 },
+        }),
+      },
+      {
+        value: '8 hours',
+        text: i18n.translate('xpack.ml.jobsList.datafeedModal.8hourOption', {
+          defaultMessage: '{count} hours',
+          values: { count: 8 },
+        }),
+      },
+      {
+        value: '12 hours',
+        text: i18n.translate('xpack.ml.jobsList.datafeedModal.12hourOption', {
+          defaultMessage: '{count} hours',
+          values: { count: 12 },
+        }),
+      },
+      {
+        value: '24 hours',
+        text: i18n.translate('xpack.ml.jobsList.datafeedModal.24hourOption', {
+          defaultMessage: '{count} hours',
+          values: { count: 24 },
+        }),
+      }
+    );
+  }
+
+  if ((unit === 'm' && count >= 5 && count <= 15) || unit === 'h') {
+    intervalOptions.push(
+      {
+        value: '48 hours',
+        text: i18n.translate('xpack.ml.jobsList.datafeedModal.48hourOption', {
+          defaultMessage: '{count} hours',
+          values: { count: 48 },
+        }),
+      },
+      {
+        value: '72 hours',
+        text: i18n.translate('xpack.ml.jobsList.datafeedModal.72hourOption', {
+          defaultMessage: '{count} hours',
+          values: { count: 72 },
+        }),
+      }
+    );
+  }
+
+  if ((unit === 'm' && count >= 10 && count <= 15) || unit === 'h' || unit === 'd') {
+    intervalOptions.push(
+      {
+        value: '5 days',
+        text: i18n.translate('xpack.ml.jobsList.datafeedModal.5daysOption', {
+          defaultMessage: '{count} days',
+          values: { count: 5 },
+        }),
+      },
+      {
+        value: '7 days',
+        text: i18n.translate('xpack.ml.jobsList.datafeedModal.7daysOption', {
+          defaultMessage: '{count} days',
+          values: { count: 7 },
+        }),
+      }
+    );
+  }
+
+  if (unit === 'h' || unit === 'd') {
+    intervalOptions.push({
+      value: '14 days',
+      text: i18n.translate('xpack.ml.jobsList.datafeedModal.14DaysOption', {
+        defaultMessage: '{count} days',
+        values: { count: 14 },
+      }),
+    });
+  }
+
+  return intervalOptions;
+};
diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/index.ts b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/index.ts
new file mode 100644
index 0000000000000..68c50c6663e1d
--- /dev/null
+++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_modal/index.ts
@@ -0,0 +1,8 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export { DatafeedModal } from './datafeed_modal';
diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js
index bd85420397218..cc6db66dc1cfd 100644
--- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js
+++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js
@@ -21,8 +21,8 @@ import { TIME_FORMAT } from '../../../../../../common/constants/time_format';
 import {
   EuiBasicTable,
   EuiButtonIcon,
-  EuiScreenReaderOnly,
   EuiIcon,
+  EuiScreenReaderOnly,
   EuiToolTip,
 } from '@elastic/eui';
 import { i18n } from '@kbn/i18n';
diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.d.ts b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.d.ts
index 82cbf8424973c..76e1e87312a4a 100644
--- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.d.ts
+++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.d.ts
@@ -5,4 +5,7 @@
  * 2.0.
  */
 
+import { CombinedJobWithStats } from '../../../../../common/types/anomaly_detection_jobs';
+
 export function deleteJobs(jobs: Array<{ id: string }>, callback?: () => void): Promise<void>;
+export function loadFullJob(jobId: string): Promise<CombinedJobWithStats>;
diff --git a/x-pack/plugins/ml/public/application/routing/ml_page_wrapper.tsx b/x-pack/plugins/ml/public/application/routing/ml_page_wrapper.tsx
new file mode 100644
index 0000000000000..e97ab0fb830a5
--- /dev/null
+++ b/x-pack/plugins/ml/public/application/routing/ml_page_wrapper.tsx
@@ -0,0 +1,12 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+import React, { FC } from 'react';
+import { TrackApplicationView } from '../../../../../../src/plugins/usage_collection/public';
+
+export const MlPageWrapper: FC<{ path: string }> = ({ path, children }) => {
+  return <TrackApplicationView viewId={path}>{children}</TrackApplicationView>;
+};
diff --git a/x-pack/plugins/ml/public/application/routing/router.tsx b/x-pack/plugins/ml/public/application/routing/router.tsx
index 27de3781bc7ab..c2129ef18df3a 100644
--- a/x-pack/plugins/ml/public/application/routing/router.tsx
+++ b/x-pack/plugins/ml/public/application/routing/router.tsx
@@ -18,6 +18,7 @@ import { MlContext, MlContextValue } from '../contexts/ml';
 import { UrlStateProvider } from '../util/url_state';
 
 import * as routes from './routes';
+import { MlPageWrapper } from './ml_page_wrapper';
 
 // custom RouteProps making location non-optional
 interface MlRouteProps extends RouteProps {
@@ -97,7 +98,9 @@ const MlRoutes: FC<{
               window.setTimeout(() => {
                 pageDeps.setBreadcrumbs(route.breadcrumbs);
               });
-              return route.render(props, pageDeps);
+              return (
+                <MlPageWrapper path={route.path}>{route.render(props, pageDeps)}</MlPageWrapper>
+              );
             }}
           />
         );
diff --git a/x-pack/plugins/ml/public/application/services/ml_api_service/index.ts b/x-pack/plugins/ml/public/application/services/ml_api_service/index.ts
index d66805b4f737f..1bfc597ba0b10 100644
--- a/x-pack/plugins/ml/public/application/services/ml_api_service/index.ts
+++ b/x-pack/plugins/ml/public/application/services/ml_api_service/index.ts
@@ -235,7 +235,7 @@ export function mlApiServicesProvider(httpService: HttpService) {
       datafeedConfig,
     }: {
       datafeedId: string;
-      datafeedConfig: Datafeed;
+      datafeedConfig: Partial<Datafeed>;
     }) {
       const body = JSON.stringify(datafeedConfig);
       return httpService.http<any>({
diff --git a/x-pack/plugins/ml/public/application/services/ml_api_service/results.ts b/x-pack/plugins/ml/public/application/services/ml_api_service/results.ts
index 76d6c19c165a1..19ba5aa304bf0 100644
--- a/x-pack/plugins/ml/public/application/services/ml_api_service/results.ts
+++ b/x-pack/plugins/ml/public/application/services/ml_api_service/results.ts
@@ -141,4 +141,17 @@ export const resultsApiProvider = (httpService: HttpService) => ({
       body,
     });
   },
+
+  getDatafeedResultChartData(jobId: string, start: number, end: number) {
+    const body = JSON.stringify({
+      jobId,
+      start,
+      end,
+    });
+    return httpService.http<any>({
+      path: `${basePath()}/results/datafeed_results_chart`,
+      method: 'POST',
+      body,
+    });
+  },
 });
diff --git a/x-pack/plugins/ml/public/plugin.ts b/x-pack/plugins/ml/public/plugin.ts
index 1191f3b253fd7..e3a4a8348ebc1 100644
--- a/x-pack/plugins/ml/public/plugin.ts
+++ b/x-pack/plugins/ml/public/plugin.ts
@@ -52,6 +52,7 @@ import {
 import { DataVisualizerPluginStart } from '../../data_visualizer/public';
 import { PluginSetupContract as AlertingSetup } from '../../alerting/public';
 import { registerManagementSection } from './application/management';
+import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/public';
 
 export interface MlStartDependencies {
   data: DataPublicPluginStart;
@@ -78,6 +79,7 @@ export interface MlSetupDependencies {
   share: SharePluginSetup;
   triggersActionsUi?: TriggersAndActionsUIPublicPluginSetup;
   alerting?: AlertingSetup;
+  usageCollection?: UsageCollectionSetup;
 }
 
 export type MlCoreSetup = CoreSetup<MlStartDependencies, MlPluginStart>;
@@ -121,6 +123,7 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
             kibanaVersion,
             triggersActionsUi: pluginsStart.triggersActionsUi,
             dataVisualizer: pluginsStart.dataVisualizer,
+            usageCollection: pluginsSetup.usageCollection,
           },
           params
         );
diff --git a/x-pack/plugins/ml/server/models/results_service/results_service.ts b/x-pack/plugins/ml/server/models/results_service/results_service.ts
index 225a988298b1c..9413ee00184d2 100644
--- a/x-pack/plugins/ml/server/models/results_service/results_service.ts
+++ b/x-pack/plugins/ml/server/models/results_service/results_service.ts
@@ -5,9 +5,10 @@
  * 2.0.
  */
 
-import { sortBy, slice, get } from 'lodash';
+import { sortBy, slice, get, cloneDeep } from 'lodash';
 import moment from 'moment';
 import Boom from '@hapi/boom';
+import { IScopedClusterClient } from 'kibana/server';
 import { buildAnomalyTableItems } from './build_anomaly_table_items';
 import { ANOMALIES_TABLE_DEFAULT_QUERY_SIZE } from '../../../common/constants/search';
 import { getPartitionFieldsValuesFactory } from './get_partition_fields_values';
@@ -17,9 +18,15 @@ import {
   AnomalyRecordDoc,
 } from '../../../common/types/anomalies';
 import { JOB_ID, PARTITION_FIELD_VALUE } from '../../../common/constants/anomalies';
-import { GetStoppedPartitionResult } from '../../../common/types/results';
+import {
+  GetStoppedPartitionResult,
+  GetDatafeedResultsChartDataResult,
+  defaultSearchQuery,
+  DatafeedResultsChartDataParams,
+} from '../../../common/types/results';
 import { MlJobsResponse } from '../../../common/types/job_service';
 import type { MlClient } from '../../lib/ml_client';
+import { datafeedsProvider } from '../job_service/datafeeds';
 
 // Service for carrying out Elasticsearch queries to obtain data for the
 // ML Results dashboards.
@@ -37,7 +44,7 @@ interface Influencer {
   fieldValue: any;
 }
 
-export function resultsServiceProvider(mlClient: MlClient) {
+export function resultsServiceProvider(mlClient: MlClient, client?: IScopedClusterClient) {
   // Obtains data for the anomalies table, aggregating anomalies by day or hour as requested.
   // Return an Object with properties 'anomalies' and 'interval' (interval used to aggregate anomalies,
   // one of day, hour or second. Note 'auto' can be provided as the aggregationInterval in the request,
@@ -605,6 +612,105 @@ export function resultsServiceProvider(mlClient: MlClient) {
     return finalResults;
   }
 
+  async function getDatafeedResultsChartData({
+    jobId,
+    start,
+    end,
+  }: DatafeedResultsChartDataParams): Promise<GetDatafeedResultsChartDataResult> {
+    const finalResults: GetDatafeedResultsChartDataResult = {
+      bucketResults: [],
+      datafeedResults: [],
+    };
+
+    const { getDatafeedByJobId } = datafeedsProvider(client!, mlClient);
+    const datafeedConfig = await getDatafeedByJobId(jobId);
+
+    const { body: jobsResponse } = await mlClient.getJobs({ job_id: jobId });
+    if (jobsResponse.count === 0 || jobsResponse.jobs === undefined) {
+      throw Boom.notFound(`Job with the id "${jobId}" not found`);
+    }
+
+    const jobConfig = jobsResponse.jobs[0];
+    const timefield = jobConfig.data_description.time_field;
+    const bucketSpan = jobConfig.analysis_config.bucket_span;
+
+    if (datafeedConfig === undefined) {
+      return finalResults;
+    }
+
+    const rangeFilter = {
+      range: {
+        [timefield]: { gte: start, lte: end },
+      },
+    };
+
+    let datafeedQueryClone =
+      datafeedConfig.query !== undefined ? cloneDeep(datafeedConfig.query) : defaultSearchQuery;
+
+    if (datafeedQueryClone.bool !== undefined) {
+      if (datafeedQueryClone.bool.filter === undefined) {
+        datafeedQueryClone.bool.filter = [];
+      }
+      if (Array.isArray(datafeedQueryClone.bool.filter)) {
+        datafeedQueryClone.bool.filter.push(rangeFilter);
+      } else {
+        // filter is an object so convert to array so we can add the rangeFilter
+        const filterQuery = cloneDeep(datafeedQueryClone.bool.filter);
+        datafeedQueryClone.bool.filter = [filterQuery, rangeFilter];
+      }
+    } else {
+      // Not a bool query so convert to a bool query so we can add the range filter
+      datafeedQueryClone = { bool: { must: [datafeedQueryClone], filter: [rangeFilter] } };
+    }
+
+    const esSearchRequest = {
+      index: datafeedConfig.indices.join(','),
+      body: {
+        query: datafeedQueryClone,
+        ...(datafeedConfig.runtime_mappings
+          ? { runtime_mappings: datafeedConfig.runtime_mappings }
+          : {}),
+        aggs: {
+          doc_count_by_bucket_span: {
+            date_histogram: {
+              field: timefield,
+              fixed_interval: bucketSpan,
+            },
+          },
+        },
+        size: 0,
+      },
+      ...(datafeedConfig?.indices_options ?? {}),
+    };
+
+    if (client) {
+      const {
+        body: { aggregations },
+      } = await client.asCurrentUser.search(esSearchRequest);
+
+      finalResults.datafeedResults =
+        // @ts-expect-error incorrect search response type
+        aggregations?.doc_count_by_bucket_span?.buckets.map((result) => [
+          result.key,
+          result.doc_count,
+        ]) || [];
+    }
+
+    const bucketResp = await mlClient.getBuckets({
+      job_id: jobId,
+      body: { desc: true, start: String(start), end: String(end), page: { from: 0, size: 1000 } },
+    });
+
+    const bucketResults = bucketResp?.body?.buckets ?? [];
+    bucketResults.forEach((dataForTime) => {
+      const timestamp = Number(dataForTime?.timestamp);
+      const eventCount = dataForTime?.event_count;
+      finalResults.bucketResults.push([timestamp, eventCount]);
+    });
+
+    return finalResults;
+  }
+
   return {
     getAnomaliesTableData,
     getCategoryDefinition,
@@ -614,5 +720,6 @@ export function resultsServiceProvider(mlClient: MlClient) {
     getPartitionFieldsValues: getPartitionFieldsValuesFactory(mlClient),
     getCategorizerStats,
     getCategoryStoppedPartitions,
+    getDatafeedResultsChartData,
   };
 }
diff --git a/x-pack/plugins/ml/server/routes/apidoc.json b/x-pack/plugins/ml/server/routes/apidoc.json
index 16cd3ea8df629..ba712583f1b61 100644
--- a/x-pack/plugins/ml/server/routes/apidoc.json
+++ b/x-pack/plugins/ml/server/routes/apidoc.json
@@ -48,6 +48,7 @@
 
     "ResultsService",
     "GetAnomaliesTableData",
+    "GetDatafeedResultsChartData",
     "GetCategoryDefinition",
     "GetMaxAnomalyScore",
     "GetCategoryExamples",
diff --git a/x-pack/plugins/ml/server/routes/results_service.ts b/x-pack/plugins/ml/server/routes/results_service.ts
index 1962463a06677..2cb34ce357fea 100644
--- a/x-pack/plugins/ml/server/routes/results_service.ts
+++ b/x-pack/plugins/ml/server/routes/results_service.ts
@@ -11,6 +11,7 @@ import {
   anomaliesTableDataSchema,
   categoryDefinitionSchema,
   categoryExamplesSchema,
+  getDatafeedResultsChartDataSchema,
   maxAnomalyScoreSchema,
   partitionFieldValuesSchema,
   anomalySearchSchema,
@@ -352,4 +353,37 @@ export function resultsServiceRoutes({ router, routeGuard }: RouteInitialization
       }
     })
   );
+
+  /**
+   * @apiGroup ResultsService
+   *
+   * @api {post} /api/ml/results/datafeed_results_chart Get datafeed results chart data
+   * @apiName GetDatafeedResultsChartData
+   * @apiDescription Returns datafeed results chart data
+   *
+   * @apiSchema (body) getDatafeedResultsChartDataSchema
+   */
+  router.post(
+    {
+      path: '/api/ml/results/datafeed_results_chart',
+      validate: {
+        body: getDatafeedResultsChartDataSchema,
+      },
+      options: {
+        tags: ['access:ml:canGetJobs'],
+      },
+    },
+    routeGuard.fullLicenseAPIGuard(async ({ client, mlClient, request, response }) => {
+      try {
+        const { getDatafeedResultsChartData } = resultsServiceProvider(mlClient, client);
+        const resp = await getDatafeedResultsChartData(request.body);
+
+        return response.ok({
+          body: resp,
+        });
+      } catch (e) {
+        return response.customError(wrapError(e));
+      }
+    })
+  );
 }
diff --git a/x-pack/plugins/ml/server/routes/schemas/results_service_schema.ts b/x-pack/plugins/ml/server/routes/schemas/results_service_schema.ts
index 175300f88166a..df4a56b06410b 100644
--- a/x-pack/plugins/ml/server/routes/schemas/results_service_schema.ts
+++ b/x-pack/plugins/ml/server/routes/schemas/results_service_schema.ts
@@ -103,3 +103,12 @@ export const getCategorizerStoppedPartitionsSchema = schema.object({
    */
   fieldToBucket: schema.maybe(schema.string()),
 });
+
+export const getDatafeedResultsChartDataSchema = schema.object({
+  /**
+   * Job id to fetch the bucket results for
+   */
+  jobId: schema.string(),
+  start: schema.number(),
+  end: schema.number(),
+});
diff --git a/x-pack/plugins/observability/common/const.ts b/x-pack/plugins/observability/common/const.ts
new file mode 100644
index 0000000000000..7065d8ccc6b34
--- /dev/null
+++ b/x-pack/plugins/observability/common/const.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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export const CASES_APP_ID = 'observabilityCases';
+export const OBSERVABILITY = 'observability';
diff --git a/x-pack/plugins/observability/kibana.json b/x-pack/plugins/observability/kibana.json
index 52d5493ae69a4..d13140f0be16c 100644
--- a/x-pack/plugins/observability/kibana.json
+++ b/x-pack/plugins/observability/kibana.json
@@ -7,14 +7,16 @@
     "observability"
   ],
   "optionalPlugins": [
-    "licensing",
     "home",
-    "usageCollection",
-    "lens"
+    "lens",
+    "licensing",
+    "usageCollection"
   ],
   "requiredPlugins": [
-    "data",
     "alerting",
+    "cases",
+    "data",
+    "features",
     "ruleRegistry",
     "triggersActionsUi"
   ],
diff --git a/x-pack/plugins/observability/public/components/app/cases/all_cases/index.tsx b/x-pack/plugins/observability/public/components/app/cases/all_cases/index.tsx
new file mode 100644
index 0000000000000..1636d08aa56e4
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/all_cases/index.tsx
@@ -0,0 +1,74 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import {
+  getCaseDetailsUrl,
+  getConfigureCasesUrl,
+  getCreateCaseUrl,
+  useFormatUrl,
+} from '../../../../pages/cases/links';
+import { useKibana } from '../../../../utils/kibana_react';
+import { CASES_APP_ID, CASES_OWNER } from '../constants';
+
+export interface AllCasesNavProps {
+  detailName: string;
+  search?: string;
+  subCaseId?: string;
+}
+
+interface AllCasesProps {
+  userCanCrud: boolean;
+}
+export const AllCases = React.memo<AllCasesProps>(({ userCanCrud }) => {
+  const {
+    cases: casesUi,
+    application: { navigateToApp },
+  } = useKibana().services;
+  const { formatUrl } = useFormatUrl(CASES_APP_ID);
+
+  return casesUi.getAllCases({
+    caseDetailsNavigation: {
+      href: ({ detailName, subCaseId }: AllCasesNavProps) => {
+        return formatUrl(getCaseDetailsUrl({ id: detailName, subCaseId }));
+      },
+      onClick: async ({ detailName, subCaseId, search }: AllCasesNavProps) =>
+        navigateToApp(`${CASES_APP_ID}`, {
+          path: getCaseDetailsUrl({ id: detailName, subCaseId }),
+        }),
+    },
+    configureCasesNavigation: {
+      href: formatUrl(getConfigureCasesUrl()),
+      onClick: async (ev) => {
+        if (ev != null) {
+          ev.preventDefault();
+        }
+        return navigateToApp(`${CASES_APP_ID}`, {
+          path: getConfigureCasesUrl(),
+        });
+      },
+    },
+    createCaseNavigation: {
+      href: formatUrl(getCreateCaseUrl()),
+      onClick: async (ev) => {
+        if (ev != null) {
+          ev.preventDefault();
+        }
+        return navigateToApp(`${CASES_APP_ID}`, {
+          path: getCreateCaseUrl(),
+        });
+      },
+    },
+    disableAlerts: true,
+    showTitle: false,
+    userCanCrud,
+    owner: [CASES_OWNER],
+  });
+});
+
+AllCases.displayName = 'AllCases';
diff --git a/x-pack/plugins/observability/public/components/app/cases/callout/callout.test.tsx b/x-pack/plugins/observability/public/components/app/cases/callout/callout.test.tsx
new file mode 100644
index 0000000000000..b0b6fc0e3b793
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/callout/callout.test.tsx
@@ -0,0 +1,90 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { mount } from 'enzyme';
+
+import { CallOut, CallOutProps } from './callout';
+
+describe('Callout', () => {
+  const defaultProps: CallOutProps = {
+    id: 'md5-hex',
+    type: 'primary',
+    title: 'a tittle',
+    messages: [
+      {
+        id: 'generic-error',
+        title: 'message-one',
+        description: <p>{'error'}</p>,
+      },
+    ],
+    showCallOut: true,
+    handleDismissCallout: jest.fn(),
+  };
+
+  beforeEach(() => {
+    jest.clearAllMocks();
+  });
+
+  it('renders the callout', () => {
+    const wrapper = mount(<CallOut {...defaultProps} />);
+    expect(wrapper.find(`[data-test-subj="case-callout-md5-hex"]`).exists()).toBeTruthy();
+    expect(wrapper.find(`[data-test-subj="callout-messages-md5-hex"]`).exists()).toBeTruthy();
+    expect(wrapper.find(`[data-test-subj="callout-dismiss-md5-hex"]`).exists()).toBeTruthy();
+  });
+
+  it('hides the callout', () => {
+    const wrapper = mount(<CallOut {...defaultProps} showCallOut={false} />);
+    expect(wrapper.find(`[data-test-subj="case-callout-md5-hex"]`).exists()).toBeFalsy();
+  });
+
+  it('does not show any messages when the list is empty', () => {
+    const wrapper = mount(<CallOut {...defaultProps} messages={[]} />);
+    expect(wrapper.find(`[data-test-subj="callout-messages-md5-hex"]`).exists()).toBeFalsy();
+  });
+
+  it('transform the button color correctly - primary', () => {
+    const wrapper = mount(<CallOut {...defaultProps} />);
+    const className =
+      wrapper.find(`button[data-test-subj="callout-dismiss-md5-hex"]`).first().prop('className') ??
+      '';
+    expect(className.includes('euiButton--primary')).toBeTruthy();
+  });
+
+  it('transform the button color correctly - success', () => {
+    const wrapper = mount(<CallOut {...defaultProps} type={'success'} />);
+    const className =
+      wrapper.find(`button[data-test-subj="callout-dismiss-md5-hex"]`).first().prop('className') ??
+      '';
+    expect(className.includes('euiButton--secondary')).toBeTruthy();
+  });
+
+  it('transform the button color correctly - warning', () => {
+    const wrapper = mount(<CallOut {...defaultProps} type={'warning'} />);
+    const className =
+      wrapper.find(`button[data-test-subj="callout-dismiss-md5-hex"]`).first().prop('className') ??
+      '';
+    expect(className.includes('euiButton--warning')).toBeTruthy();
+  });
+
+  it('transform the button color correctly - danger', () => {
+    const wrapper = mount(<CallOut {...defaultProps} type={'danger'} />);
+    const className =
+      wrapper.find(`button[data-test-subj="callout-dismiss-md5-hex"]`).first().prop('className') ??
+      '';
+    expect(className.includes('euiButton--danger')).toBeTruthy();
+  });
+
+  it('dismiss the callout correctly', () => {
+    const wrapper = mount(<CallOut {...defaultProps} />);
+    expect(wrapper.find(`[data-test-subj="callout-dismiss-md5-hex"]`).exists()).toBeTruthy();
+    wrapper.find(`button[data-test-subj="callout-dismiss-md5-hex"]`).simulate('click');
+    wrapper.update();
+
+    expect(defaultProps.handleDismissCallout).toHaveBeenCalledWith('md5-hex', 'primary');
+  });
+});
diff --git a/x-pack/plugins/observability/public/components/app/cases/callout/callout.tsx b/x-pack/plugins/observability/public/components/app/cases/callout/callout.tsx
new file mode 100644
index 0000000000000..4cb3875f75acb
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/callout/callout.tsx
@@ -0,0 +1,52 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { EuiCallOut, EuiButton, EuiDescriptionList } from '@elastic/eui';
+import { isEmpty } from 'lodash/fp';
+import React, { memo, useCallback } from 'react';
+
+import { ErrorMessage } from './types';
+import * as i18n from './translations';
+
+export interface CallOutProps {
+  id: string;
+  type: NonNullable<ErrorMessage['errorType']>;
+  title: string;
+  messages: ErrorMessage[];
+  showCallOut: boolean;
+  handleDismissCallout: (id: string, type: NonNullable<ErrorMessage['errorType']>) => void;
+}
+
+function CallOutComponent({
+  id,
+  type,
+  title,
+  messages,
+  showCallOut,
+  handleDismissCallout,
+}: CallOutProps) {
+  const handleCallOut = useCallback(() => handleDismissCallout(id, type), [
+    handleDismissCallout,
+    id,
+    type,
+  ]);
+
+  return showCallOut && !isEmpty(messages) ? (
+    <EuiCallOut title={title} color={type} iconType="gear" data-test-subj={`case-callout-${id}`}>
+      <EuiDescriptionList data-test-subj={`callout-messages-${id}`} listItems={messages} />
+      <EuiButton
+        data-test-subj={`callout-dismiss-${id}`}
+        color={type === 'success' ? 'secondary' : type}
+        onClick={handleCallOut}
+      >
+        {i18n.DISMISS_CALLOUT}
+      </EuiButton>
+    </EuiCallOut>
+  ) : null;
+}
+
+export const CallOut = memo(CallOutComponent);
diff --git a/x-pack/plugins/observability/public/components/app/cases/callout/helpers.test.tsx b/x-pack/plugins/observability/public/components/app/cases/callout/helpers.test.tsx
new file mode 100644
index 0000000000000..b5b92a3374874
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/callout/helpers.test.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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import md5 from 'md5';
+import { createCalloutId } from './helpers';
+
+describe('createCalloutId', () => {
+  it('creates id correctly with one id', () => {
+    const digest = md5('one');
+    const id = createCalloutId(['one']);
+    expect(id).toBe(digest);
+  });
+
+  it('creates id correctly with multiples ids', () => {
+    const digest = md5('one|two|three');
+    const id = createCalloutId(['one', 'two', 'three']);
+    expect(id).toBe(digest);
+  });
+
+  it('creates id correctly with multiples ids and delimiter', () => {
+    const digest = md5('one,two,three');
+    const id = createCalloutId(['one', 'two', 'three'], ',');
+    expect(id).toBe(digest);
+  });
+});
diff --git a/x-pack/plugins/observability/public/components/app/cases/callout/helpers.tsx b/x-pack/plugins/observability/public/components/app/cases/callout/helpers.tsx
new file mode 100644
index 0000000000000..29b17cd426c58
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/callout/helpers.tsx
@@ -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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import md5 from 'md5';
+
+import * as i18n from './translations';
+import { ErrorMessage } from './types';
+
+export const permissionsReadOnlyErrorMessage: ErrorMessage = {
+  id: 'read-only-privileges-error',
+  title: i18n.READ_ONLY_FEATURE_TITLE,
+  description: <>{i18n.READ_ONLY_FEATURE_MSG}</>,
+  errorType: 'warning',
+};
+
+export const createCalloutId = (ids: string[], delimiter: string = '|'): string =>
+  md5(ids.join(delimiter));
diff --git a/x-pack/plugins/observability/public/components/app/cases/callout/index.test.tsx b/x-pack/plugins/observability/public/components/app/cases/callout/index.test.tsx
new file mode 100644
index 0000000000000..e7ed339d99e90
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/callout/index.test.tsx
@@ -0,0 +1,216 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { mount } from 'enzyme';
+
+import { EuiThemeProvider } from '../../../../../../../../src/plugins/kibana_react/common';
+import { useMessagesStorage } from '../../../../hooks/use_messages_storage';
+import { createCalloutId } from './helpers';
+import { CaseCallOut, CaseCallOutProps } from '.';
+
+jest.mock('../../../../hooks/use_messages_storage');
+const useSecurityLocalStorageMock = useMessagesStorage as jest.Mock;
+const securityLocalStorageMock = {
+  getMessages: jest.fn(() => []),
+  addMessage: jest.fn(),
+};
+
+describe('CaseCallOut ', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    useSecurityLocalStorageMock.mockImplementation(() => securityLocalStorageMock);
+  });
+
+  it('renders a callout correctly', () => {
+    const props: CaseCallOutProps = {
+      title: 'hey title',
+      messages: [
+        { id: 'message-one', title: 'title', description: <p>{'we have two messages'}</p> },
+        { id: 'message-two', title: 'title', description: <p>{'for real'}</p> },
+      ],
+    };
+    const wrapper = mount(
+      <EuiThemeProvider>
+        <CaseCallOut {...props} />
+      </EuiThemeProvider>
+    );
+
+    const id = createCalloutId(['message-one', 'message-two']);
+    expect(wrapper.find(`[data-test-subj="callout-messages-${id}"]`).last().exists()).toBeTruthy();
+  });
+
+  it('groups the messages correctly', () => {
+    const props: CaseCallOutProps = {
+      title: 'hey title',
+      messages: [
+        {
+          id: 'message-one',
+          title: 'title one',
+          description: <p>{'we have two messages'}</p>,
+          errorType: 'danger',
+        },
+        { id: 'message-two', title: 'title two', description: <p>{'for real'}</p> },
+      ],
+    };
+
+    const wrapper = mount(
+      <EuiThemeProvider>
+        <CaseCallOut {...props} />
+      </EuiThemeProvider>
+    );
+
+    const idDanger = createCalloutId(['message-one']);
+    const idPrimary = createCalloutId(['message-two']);
+
+    expect(
+      wrapper.find(`[data-test-subj="case-callout-${idPrimary}"]`).last().exists()
+    ).toBeTruthy();
+    expect(
+      wrapper.find(`[data-test-subj="case-callout-${idDanger}"]`).last().exists()
+    ).toBeTruthy();
+  });
+
+  it('dismisses the callout correctly', () => {
+    const props: CaseCallOutProps = {
+      title: 'hey title',
+      messages: [
+        { id: 'message-one', title: 'title', description: <p>{'we have two messages'}</p> },
+      ],
+    };
+    const wrapper = mount(
+      <EuiThemeProvider>
+        <CaseCallOut {...props} />
+      </EuiThemeProvider>
+    );
+
+    const id = createCalloutId(['message-one']);
+
+    expect(wrapper.find(`[data-test-subj="case-callout-${id}"]`).last().exists()).toBeTruthy();
+    wrapper.find(`[data-test-subj="callout-dismiss-${id}"]`).last().simulate('click');
+    expect(wrapper.find(`[data-test-subj="case-callout-${id}"]`).exists()).toBeFalsy();
+  });
+
+  it('persist the callout of type primary when dismissed', () => {
+    const props: CaseCallOutProps = {
+      title: 'hey title',
+      messages: [
+        { id: 'message-one', title: 'title', description: <p>{'we have two messages'}</p> },
+      ],
+    };
+
+    const wrapper = mount(
+      <EuiThemeProvider>
+        <CaseCallOut {...props} />
+      </EuiThemeProvider>
+    );
+
+    const id = createCalloutId(['message-one']);
+    expect(securityLocalStorageMock.getMessages).toHaveBeenCalledWith('observability');
+    wrapper.find(`[data-test-subj="callout-dismiss-${id}"]`).last().simulate('click');
+    expect(securityLocalStorageMock.addMessage).toHaveBeenCalledWith('observability', id);
+  });
+
+  it('do not show the callout if is in the localStorage', () => {
+    const props: CaseCallOutProps = {
+      title: 'hey title',
+      messages: [
+        { id: 'message-one', title: 'title', description: <p>{'we have two messages'}</p> },
+      ],
+    };
+
+    const id = createCalloutId(['message-one']);
+
+    useSecurityLocalStorageMock.mockImplementation(() => ({
+      ...securityLocalStorageMock,
+      getMessages: jest.fn(() => [id]),
+    }));
+
+    const wrapper = mount(
+      <EuiThemeProvider>
+        <CaseCallOut {...props} />
+      </EuiThemeProvider>
+    );
+
+    expect(wrapper.find(`[data-test-subj="case-callout-${id}"]`).last().exists()).toBeFalsy();
+  });
+
+  it('do not persist a callout of type danger', () => {
+    const props: CaseCallOutProps = {
+      title: 'hey title',
+      messages: [
+        {
+          id: 'message-one',
+          title: 'title one',
+          description: <p>{'we have two messages'}</p>,
+          errorType: 'danger',
+        },
+      ],
+    };
+
+    const wrapper = mount(
+      <EuiThemeProvider>
+        <CaseCallOut {...props} />
+      </EuiThemeProvider>
+    );
+
+    const id = createCalloutId(['message-one']);
+    wrapper.find(`button[data-test-subj="callout-dismiss-${id}"]`).simulate('click');
+    wrapper.update();
+    expect(securityLocalStorageMock.addMessage).not.toHaveBeenCalled();
+  });
+
+  it('do not persist a callout of type warning', () => {
+    const props: CaseCallOutProps = {
+      title: 'hey title',
+      messages: [
+        {
+          id: 'message-one',
+          title: 'title one',
+          description: <p>{'we have two messages'}</p>,
+          errorType: 'warning',
+        },
+      ],
+    };
+
+    const wrapper = mount(
+      <EuiThemeProvider>
+        <CaseCallOut {...props} />
+      </EuiThemeProvider>
+    );
+
+    const id = createCalloutId(['message-one']);
+    wrapper.find(`button[data-test-subj="callout-dismiss-${id}"]`).simulate('click');
+    wrapper.update();
+    expect(securityLocalStorageMock.addMessage).not.toHaveBeenCalled();
+  });
+
+  it('do not persist a callout of type success', () => {
+    const props: CaseCallOutProps = {
+      title: 'hey title',
+      messages: [
+        {
+          id: 'message-one',
+          title: 'title one',
+          description: <p>{'we have two messages'}</p>,
+          errorType: 'success',
+        },
+      ],
+    };
+
+    const wrapper = mount(
+      <EuiThemeProvider>
+        <CaseCallOut {...props} />
+      </EuiThemeProvider>
+    );
+
+    const id = createCalloutId(['message-one']);
+    wrapper.find(`button[data-test-subj="callout-dismiss-${id}"]`).simulate('click');
+    wrapper.update();
+    expect(securityLocalStorageMock.addMessage).not.toHaveBeenCalled();
+  });
+});
diff --git a/x-pack/plugins/observability/public/components/app/cases/callout/index.tsx b/x-pack/plugins/observability/public/components/app/cases/callout/index.tsx
new file mode 100644
index 0000000000000..43cb6fd352a53
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/callout/index.tsx
@@ -0,0 +1,104 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { EuiSpacer } from '@elastic/eui';
+import React, { memo, useCallback, useState, useMemo } from 'react';
+
+import { CallOut } from './callout';
+import { ErrorMessage } from './types';
+import { createCalloutId } from './helpers';
+import { useMessagesStorage } from '../../../../hooks/use_messages_storage';
+import { OBSERVABILITY } from '../../../../../common/const';
+
+export * from './helpers';
+
+export interface CaseCallOutProps {
+  title: string;
+  messages?: ErrorMessage[];
+}
+
+type GroupByTypeMessages = {
+  [key in NonNullable<ErrorMessage['errorType']>]: {
+    messagesId: string[];
+    messages: ErrorMessage[];
+  };
+};
+
+interface CalloutVisibility {
+  [index: string]: boolean;
+}
+
+function CaseCallOutComponent({ title, messages = [] }: CaseCallOutProps) {
+  const { getMessages, addMessage } = useMessagesStorage();
+
+  const caseMessages = useMemo(() => getMessages(OBSERVABILITY), [getMessages]);
+  const dismissedCallouts = useMemo(
+    () =>
+      caseMessages.reduce<CalloutVisibility>(
+        (acc: CalloutVisibility, id) => ({
+          ...acc,
+          [id]: false,
+        }),
+        {}
+      ),
+    [caseMessages]
+  );
+
+  const [calloutVisibility, setCalloutVisibility] = useState(dismissedCallouts);
+  const handleCallOut = useCallback(
+    (id, type) => {
+      setCalloutVisibility((prevState) => ({ ...prevState, [id]: false }));
+      if (type === 'primary') {
+        addMessage(OBSERVABILITY, id);
+      }
+    },
+    [setCalloutVisibility, addMessage]
+  );
+
+  const groupedByTypeErrorMessages = useMemo(
+    () =>
+      messages.reduce<GroupByTypeMessages>(
+        (acc: GroupByTypeMessages, currentMessage: ErrorMessage) => {
+          const type = currentMessage.errorType == null ? 'primary' : currentMessage.errorType;
+          return {
+            ...acc,
+            [type]: {
+              messagesId: [...(acc[type]?.messagesId ?? []), currentMessage.id],
+              messages: [...(acc[type]?.messages ?? []), currentMessage],
+            },
+          };
+        },
+        {} as GroupByTypeMessages
+      ),
+    [messages]
+  );
+
+  return (
+    <>
+      {(Object.keys(groupedByTypeErrorMessages) as Array<keyof ErrorMessage['errorType']>).map(
+        (type: NonNullable<ErrorMessage['errorType']>) => {
+          const id = createCalloutId(groupedByTypeErrorMessages[type].messagesId);
+          return (
+            <React.Fragment key={id}>
+              <CallOut
+                id={id}
+                type={type}
+                title={title}
+                messages={groupedByTypeErrorMessages[type].messages}
+                showCallOut={calloutVisibility[id] ?? true}
+                handleDismissCallout={handleCallOut}
+              />
+              <EuiSpacer />
+            </React.Fragment>
+          );
+        }
+      )}
+    </>
+  );
+}
+
+export const CaseCallOut = memo(CaseCallOutComponent);
diff --git a/x-pack/plugins/observability/public/components/app/cases/callout/translations.ts b/x-pack/plugins/observability/public/components/app/cases/callout/translations.ts
new file mode 100644
index 0000000000000..cb7236b445be1
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/callout/translations.ts
@@ -0,0 +1,30 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { i18n } from '@kbn/i18n';
+
+export const READ_ONLY_FEATURE_TITLE = i18n.translate(
+  'xpack.observability.cases.readOnlyFeatureTitle',
+  {
+    defaultMessage: 'You cannot open new or update existing cases',
+  }
+);
+
+export const READ_ONLY_FEATURE_MSG = i18n.translate(
+  'xpack.observability.cases.readOnlyFeatureDescription',
+  {
+    defaultMessage:
+      'You only have privileges to view cases. If you need to open and update cases, contact your Kibana administrator.',
+  }
+);
+
+export const DISMISS_CALLOUT = i18n.translate(
+  'xpack.observability.cases.dismissErrorsPushServiceCallOutTitle',
+  {
+    defaultMessage: 'Dismiss',
+  }
+);
diff --git a/x-pack/plugins/observability/public/components/app/cases/callout/types.ts b/x-pack/plugins/observability/public/components/app/cases/callout/types.ts
new file mode 100644
index 0000000000000..84d79ee391b8f
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/callout/types.ts
@@ -0,0 +1,13 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export interface ErrorMessage {
+  id: string;
+  title: string;
+  description: JSX.Element;
+  errorType?: 'primary' | 'success' | 'warning' | 'danger';
+}
diff --git a/x-pack/plugins/observability/public/components/app/cases/case_view/helpers.ts b/x-pack/plugins/observability/public/components/app/cases/case_view/helpers.ts
new file mode 100644
index 0000000000000..b180c15b4487a
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/case_view/helpers.ts
@@ -0,0 +1,12 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { Ecs } from '../../../../../../cases/common';
+
+// no alerts in observability so far
+// dummy hook for now as hooks cannot be called conditionally
+export const useFetchAlertData = (): [boolean, Record<string, Ecs>] => [false, {}];
diff --git a/x-pack/plugins/observability/public/components/app/cases/case_view/index.tsx b/x-pack/plugins/observability/public/components/app/cases/case_view/index.tsx
new file mode 100644
index 0000000000000..3267f7bb17cce
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/case_view/index.tsx
@@ -0,0 +1,122 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { useCallback, useState } from 'react';
+import {
+  getCaseDetailsUrl,
+  getCaseDetailsUrlWithCommentId,
+  getCaseUrl,
+  getConfigureCasesUrl,
+  useFormatUrl,
+} from '../../../../pages/cases/links';
+import { Case } from '../../../../../../cases/common';
+import { useFetchAlertData } from './helpers';
+import { useKibana } from '../../../../utils/kibana_react';
+import { CASES_APP_ID } from '../constants';
+import { casesBreadcrumbs, useBreadcrumbs } from '../../../../hooks/use_breadcrumbs';
+
+interface Props {
+  caseId: string;
+  subCaseId?: string;
+  userCanCrud: boolean;
+}
+
+export interface OnUpdateFields {
+  key: keyof Case;
+  value: Case[keyof Case];
+  onSuccess?: () => void;
+  onError?: () => void;
+}
+
+export interface CaseProps extends Props {
+  fetchCase: () => void;
+  caseData: Case;
+  updateCase: (newCase: Case) => void;
+}
+
+export const CaseView = React.memo(({ caseId, subCaseId, userCanCrud }: Props) => {
+  const [caseTitle, setCaseTitle] = useState<string | null>(null);
+
+  const { cases: casesUi, application } = useKibana().services;
+  const { navigateToApp } = application;
+  const allCasesLink = getCaseUrl();
+  const { formatUrl } = useFormatUrl(CASES_APP_ID);
+  const href = formatUrl(allCasesLink);
+  useBreadcrumbs([
+    { ...casesBreadcrumbs.cases, href },
+    ...(caseTitle !== null
+      ? [
+          {
+            text: caseTitle,
+          },
+        ]
+      : []),
+  ]);
+
+  const onCaseDataSuccess = useCallback(
+    (data: Case) => {
+      if (caseTitle === null) {
+        setCaseTitle(data.title);
+      }
+    },
+    [caseTitle]
+  );
+
+  const configureCasesLink = getConfigureCasesUrl();
+  const allCasesHref = href;
+  const configureCasesHref = formatUrl(configureCasesLink);
+  const caseDetailsHref = formatUrl(getCaseDetailsUrl({ id: caseId }), { absolute: true });
+  const getCaseDetailHrefWithCommentId = useCallback(
+    (commentId: string) =>
+      formatUrl(getCaseDetailsUrlWithCommentId({ id: caseId, commentId, subCaseId }), {
+        absolute: true,
+      }),
+    [caseId, formatUrl, subCaseId]
+  );
+
+  return casesUi.getCaseView({
+    allCasesNavigation: {
+      href: allCasesHref,
+      onClick: async (ev) => {
+        if (ev != null) {
+          ev.preventDefault();
+        }
+        return navigateToApp(`${CASES_APP_ID}`, {
+          path: allCasesLink,
+        });
+      },
+    },
+    caseDetailsNavigation: {
+      href: caseDetailsHref,
+      onClick: async (ev) => {
+        if (ev != null) {
+          ev.preventDefault();
+        }
+        return navigateToApp(`${CASES_APP_ID}`, {
+          path: getCaseDetailsUrl({ id: caseId }),
+        });
+      },
+    },
+    caseId,
+    configureCasesNavigation: {
+      href: configureCasesHref,
+      onClick: async (ev) => {
+        if (ev != null) {
+          ev.preventDefault();
+        }
+        return navigateToApp(`${CASES_APP_ID}`, {
+          path: configureCasesLink,
+        });
+      },
+    },
+    getCaseDetailHrefWithCommentId,
+    onCaseDataSuccess,
+    subCaseId,
+    useFetchAlertData,
+    userCanCrud,
+  });
+});
diff --git a/x-pack/plugins/observability/public/components/app/cases/constants.ts b/x-pack/plugins/observability/public/components/app/cases/constants.ts
new file mode 100644
index 0000000000000..3c1f868fec084
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/constants.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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { CASES_APP_ID } from '../../../../common/const';
+
+export { CASES_APP_ID };
+export const CASES_OWNER = 'observability';
diff --git a/x-pack/plugins/observability/public/components/app/cases/create/flyout.test.tsx b/x-pack/plugins/observability/public/components/app/cases/create/flyout.test.tsx
new file mode 100644
index 0000000000000..c358067123747
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/create/flyout.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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { mount } from 'enzyme';
+import { EuiThemeProvider } from '../../../../../../../../src/plugins/kibana_react/common';
+
+import { CreateCaseFlyout } from './flyout';
+
+jest.mock('../../../../utils/kibana_react', () => ({
+  useKibana: () => ({
+    services: {
+      cases: {
+        getCreateCase: jest.fn(),
+      },
+    },
+  }),
+}));
+const onCloseFlyout = jest.fn();
+const onSuccess = jest.fn();
+const defaultProps = {
+  onCloseFlyout,
+  onSuccess,
+};
+
+describe('CreateCaseFlyout', () => {
+  beforeEach(() => {
+    jest.resetAllMocks();
+  });
+
+  it('renders', () => {
+    const wrapper = mount(
+      <EuiThemeProvider>
+        <CreateCaseFlyout {...defaultProps} />
+      </EuiThemeProvider>
+    );
+
+    expect(wrapper.find(`[data-test-subj='create-case-flyout']`).exists()).toBeTruthy();
+  });
+
+  it('Closing modal calls onCloseCaseModal', () => {
+    const wrapper = mount(
+      <EuiThemeProvider>
+        <CreateCaseFlyout {...defaultProps} />
+      </EuiThemeProvider>
+    );
+
+    wrapper.find('.euiFlyout__closeButton').first().simulate('click');
+    expect(onCloseFlyout).toBeCalled();
+  });
+});
diff --git a/x-pack/plugins/observability/public/components/app/cases/create/flyout.tsx b/x-pack/plugins/observability/public/components/app/cases/create/flyout.tsx
new file mode 100644
index 0000000000000..df29d02e8d830
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/create/flyout.tsx
@@ -0,0 +1,81 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { memo } from 'react';
+import styled from 'styled-components';
+import { EuiFlyout, EuiFlyoutHeader, EuiTitle, EuiFlyoutBody } from '@elastic/eui';
+
+import * as i18n from '../translations';
+import { Case } from '../../../../../../cases/common';
+import { CASES_OWNER } from '../constants';
+import { useKibana } from '../../../../utils/kibana_react';
+
+export interface CreateCaseModalProps {
+  afterCaseCreated?: (theCase: Case) => Promise<void>;
+  onCloseFlyout: () => void;
+  onSuccess: (theCase: Case) => Promise<void>;
+}
+
+const StyledFlyout = styled(EuiFlyout)`
+  ${({ theme }) => `
+    z-index: ${theme.eui.euiZModal};
+  `}
+`;
+// Adding bottom padding because timeline's
+// bottom bar gonna hide the submit button.
+// might not need for obs, test this when implementing this component
+const StyledEuiFlyoutBody = styled(EuiFlyoutBody)`
+  ${({ theme }) => `
+    && .euiFlyoutBody__overflow {
+      overflow-y: auto;
+      overflow-x: hidden;
+    }
+
+    && .euiFlyoutBody__overflowContent {
+      display: block;
+      padding: ${theme.eui.paddingSizes.l} ${theme.eui.paddingSizes.l} 70px;
+      height: auto;
+    }
+  `}
+`;
+
+const FormWrapper = styled.div`
+  width: 100%;
+`;
+
+function CreateCaseFlyoutComponent({
+  afterCaseCreated,
+  onCloseFlyout,
+  onSuccess,
+}: CreateCaseModalProps) {
+  const { cases } = useKibana().services;
+  return (
+    <StyledFlyout onClose={onCloseFlyout} data-test-subj="create-case-flyout">
+      <EuiFlyoutHeader hasBorder>
+        <EuiTitle size="m">
+          <h2>{i18n.CREATE_TITLE}</h2>
+        </EuiTitle>
+      </EuiFlyoutHeader>
+      <StyledEuiFlyoutBody>
+        <FormWrapper>
+          {cases.getCreateCase({
+            afterCaseCreated,
+            onCancel: onCloseFlyout,
+            onSuccess,
+            withSteps: false,
+            owner: [CASES_OWNER],
+          })}
+        </FormWrapper>
+      </StyledEuiFlyoutBody>
+    </StyledFlyout>
+  );
+}
+// not yet used
+// committing for use with alerting #RAC
+export const CreateCaseFlyout = memo(CreateCaseFlyoutComponent);
+
+CreateCaseFlyout.displayName = 'CreateCaseFlyout';
diff --git a/x-pack/plugins/observability/public/components/app/cases/create/index.test.tsx b/x-pack/plugins/observability/public/components/app/cases/create/index.test.tsx
new file mode 100644
index 0000000000000..ec7511836328b
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/create/index.test.tsx
@@ -0,0 +1,90 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { mount } from 'enzyme';
+import { waitFor } from '@testing-library/react';
+import { EuiThemeProvider } from '../../../../../../../../src/plugins/kibana_react/common';
+import { Create } from '.';
+import { useKibana } from '../../../../utils/kibana_react';
+import { basicCase } from '../../../../../../cases/public/containers/mock';
+import { CASES_APP_ID, CASES_OWNER } from '../constants';
+import { Case } from '../../../../../../cases/common';
+import { getCaseDetailsUrl } from '../../../../pages/cases/links';
+
+jest.mock('../../../../utils/kibana_react');
+
+describe('Create case', () => {
+  const mockCreateCase = jest.fn();
+  const mockNavigateToApp = jest.fn();
+  beforeEach(() => {
+    jest.resetAllMocks();
+    (useKibana as jest.Mock).mockReturnValue({
+      services: {
+        cases: {
+          getCreateCase: mockCreateCase,
+        },
+        application: { navigateToApp: mockNavigateToApp },
+      },
+    });
+  });
+
+  it('it renders', () => {
+    mount(
+      <EuiThemeProvider>
+        <Create />
+      </EuiThemeProvider>
+    );
+
+    expect(mockCreateCase).toHaveBeenCalled();
+    expect(mockCreateCase.mock.calls[0][0].owner).toEqual([CASES_OWNER]);
+  });
+
+  it('should redirect to all cases on cancel click', async () => {
+    (useKibana as jest.Mock).mockReturnValue({
+      services: {
+        cases: {
+          getCreateCase: ({ onCancel }: { onCancel: () => Promise<void> }) => {
+            onCancel();
+          },
+        },
+        application: { navigateToApp: mockNavigateToApp },
+      },
+    });
+    mount(
+      <EuiThemeProvider>
+        <Create />
+      </EuiThemeProvider>
+    );
+
+    await waitFor(() => expect(mockNavigateToApp).toHaveBeenCalledWith(`${CASES_APP_ID}`));
+  });
+
+  it('should redirect to new case when posting the case', async () => {
+    (useKibana as jest.Mock).mockReturnValue({
+      services: {
+        cases: {
+          getCreateCase: ({ onSuccess }: { onSuccess: (theCase: Case) => Promise<void> }) => {
+            onSuccess(basicCase);
+          },
+        },
+        application: { navigateToApp: mockNavigateToApp },
+      },
+    });
+    mount(
+      <EuiThemeProvider>
+        <Create />
+      </EuiThemeProvider>
+    );
+
+    await waitFor(() =>
+      expect(mockNavigateToApp).toHaveBeenNthCalledWith(1, `${CASES_APP_ID}`, {
+        path: getCaseDetailsUrl({ id: basicCase.id }),
+      })
+    );
+  });
+});
diff --git a/x-pack/plugins/observability/public/components/app/cases/create/index.tsx b/x-pack/plugins/observability/public/components/app/cases/create/index.tsx
new file mode 100644
index 0000000000000..d7e2daea2490b
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/create/index.tsx
@@ -0,0 +1,42 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { useCallback } from 'react';
+import { EuiPanel } from '@elastic/eui';
+
+import { useKibana } from '../../../../utils/kibana_react';
+import { getCaseDetailsUrl } from '../../../../pages/cases/links';
+import { CASES_APP_ID, CASES_OWNER } from '../constants';
+
+export const Create = React.memo(() => {
+  const {
+    cases,
+    application: { navigateToApp },
+  } = useKibana().services;
+  const onSuccess = useCallback(
+    async ({ id }) =>
+      navigateToApp(`${CASES_APP_ID}`, {
+        path: getCaseDetailsUrl({ id }),
+      }),
+    [navigateToApp]
+  );
+
+  const handleSetIsCancel = useCallback(() => navigateToApp(`${CASES_APP_ID}`), [navigateToApp]);
+
+  return (
+    <EuiPanel>
+      {cases.getCreateCase({
+        disableAlerts: true,
+        onCancel: handleSetIsCancel,
+        onSuccess,
+        owner: [CASES_OWNER],
+      })}
+    </EuiPanel>
+  );
+});
+
+Create.displayName = 'Create';
diff --git a/x-pack/plugins/observability/public/components/app/cases/translations.ts b/x-pack/plugins/observability/public/components/app/cases/translations.ts
new file mode 100644
index 0000000000000..1a5abe218edf5
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/translations.ts
@@ -0,0 +1,203 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { i18n } from '@kbn/i18n';
+
+export const CASES_FEATURE_NO_PERMISSIONS_TITLE = i18n.translate(
+  'xpack.observability.cases.caseFeatureNoPermissionsTitle',
+  {
+    defaultMessage: 'Kibana feature privileges required',
+  }
+);
+
+export const CASES_FEATURE_NO_PERMISSIONS_MSG = i18n.translate(
+  'xpack.observability.cases.caseFeatureNoPermissionsMessage',
+  {
+    defaultMessage:
+      'To view cases, you must have privileges for the Cases feature in the Kibana space. For more information, contact your Kibana administrator.',
+  }
+);
+export const BACK_TO_ALL = i18n.translate('xpack.observability.cases.caseView.backLabel', {
+  defaultMessage: 'Back to cases',
+});
+
+export const CANCEL = i18n.translate('xpack.observability.cases.caseView.cancel', {
+  defaultMessage: 'Cancel',
+});
+
+export const DELETE_CASE = i18n.translate(
+  'xpack.observability.cases.confirmDeleteCase.deleteCase',
+  {
+    defaultMessage: 'Delete case',
+  }
+);
+
+export const DELETE_CASES = i18n.translate(
+  'xpack.observability.cases.confirmDeleteCase.deleteCases',
+  {
+    defaultMessage: 'Delete cases',
+  }
+);
+
+export const NAME = i18n.translate('xpack.observability.cases.caseView.name', {
+  defaultMessage: 'Name',
+});
+
+export const REPORTER = i18n.translate('xpack.observability.cases.caseView.reporterLabel', {
+  defaultMessage: 'Reporter',
+});
+
+export const PARTICIPANTS = i18n.translate('xpack.observability.cases.caseView.particpantsLabel', {
+  defaultMessage: 'Participants',
+});
+
+export const CREATE_TITLE = i18n.translate('xpack.observability.cases.caseView.create', {
+  defaultMessage: 'Create new case',
+});
+
+export const DESCRIPTION = i18n.translate('xpack.observability.cases.caseView.description', {
+  defaultMessage: 'Description',
+});
+
+export const DESCRIPTION_REQUIRED = i18n.translate(
+  'xpack.observability.cases.createCase.descriptionFieldRequiredError',
+  {
+    defaultMessage: 'A description is required.',
+  }
+);
+
+export const COMMENT_REQUIRED = i18n.translate(
+  'xpack.observability.cases.caseView.commentFieldRequiredError',
+  {
+    defaultMessage: 'A comment is required.',
+  }
+);
+
+export const REQUIRED_FIELD = i18n.translate(
+  'xpack.observability.cases.caseView.fieldRequiredError',
+  {
+    defaultMessage: 'Required field',
+  }
+);
+
+export const EDIT = i18n.translate('xpack.observability.cases.caseView.edit', {
+  defaultMessage: 'Edit',
+});
+
+export const OPTIONAL = i18n.translate('xpack.observability.cases.caseView.optional', {
+  defaultMessage: 'Optional',
+});
+
+export const PAGE_TITLE = i18n.translate('xpack.observability.cases.pageTitle', {
+  defaultMessage: 'Cases',
+});
+
+export const CREATE_CASE = i18n.translate('xpack.observability.cases.caseView.createCase', {
+  defaultMessage: 'Create case',
+});
+
+export const CLOSE_CASE = i18n.translate('xpack.observability.cases.caseView.closeCase', {
+  defaultMessage: 'Close case',
+});
+
+export const REOPEN_CASE = i18n.translate('xpack.observability.cases.caseView.reopenCase', {
+  defaultMessage: 'Reopen case',
+});
+
+export const CASE_NAME = i18n.translate('xpack.observability.cases.caseView.caseName', {
+  defaultMessage: 'Case name',
+});
+
+export const TO = i18n.translate('xpack.observability.cases.caseView.to', {
+  defaultMessage: 'to',
+});
+
+export const TAGS = i18n.translate('xpack.observability.cases.caseView.tags', {
+  defaultMessage: 'Tags',
+});
+
+export const ACTIONS = i18n.translate('xpack.observability.cases.allCases.actions', {
+  defaultMessage: 'Actions',
+});
+
+export const NO_TAGS_AVAILABLE = i18n.translate(
+  'xpack.observability.cases.allCases.noTagsAvailable',
+  {
+    defaultMessage: 'No tags available',
+  }
+);
+
+export const NO_REPORTERS_AVAILABLE = i18n.translate(
+  'xpack.observability.cases.caseView.noReportersAvailable',
+  {
+    defaultMessage: 'No reporters available.',
+  }
+);
+
+export const COMMENTS = i18n.translate('xpack.observability.cases.allCases.comments', {
+  defaultMessage: 'Comments',
+});
+
+export const TAGS_HELP = i18n.translate('xpack.observability.cases.createCase.fieldTagsHelpText', {
+  defaultMessage:
+    'Type one or more custom identifying tags for this case. Press enter after each tag to begin a new one.',
+});
+
+export const NO_TAGS = i18n.translate('xpack.observability.cases.caseView.noTags', {
+  defaultMessage: 'No tags are currently assigned to this case.',
+});
+
+export const TITLE_REQUIRED = i18n.translate(
+  'xpack.observability.cases.createCase.titleFieldRequiredError',
+  {
+    defaultMessage: 'A title is required.',
+  }
+);
+
+export const CONFIGURE_CASES_PAGE_TITLE = i18n.translate(
+  'xpack.observability.cases.configureCases.headerTitle',
+  {
+    defaultMessage: 'Configure cases',
+  }
+);
+
+export const CONFIGURE_CASES_BUTTON = i18n.translate(
+  'xpack.observability.cases.configureCasesButton',
+  {
+    defaultMessage: 'Edit external connection',
+  }
+);
+
+export const ADD_COMMENT = i18n.translate('xpack.observability.cases.caseView.comment.addComment', {
+  defaultMessage: 'Add comment',
+});
+
+export const ADD_COMMENT_HELP_TEXT = i18n.translate(
+  'xpack.observability.cases.caseView.comment.addCommentHelpText',
+  {
+    defaultMessage: 'Add a new comment...',
+  }
+);
+
+export const SAVE = i18n.translate('xpack.observability.cases.caseView.description.save', {
+  defaultMessage: 'Save',
+});
+
+export const GO_TO_DOCUMENTATION = i18n.translate(
+  'xpack.observability.cases.caseView.goToDocumentationButton',
+  {
+    defaultMessage: 'View documentation',
+  }
+);
+
+export const CONNECTORS = i18n.translate('xpack.observability.cases.caseView.connectors', {
+  defaultMessage: 'External Incident Management System',
+});
+
+export const EDIT_CONNECTOR = i18n.translate('xpack.observability.cases.caseView.editConnector', {
+  defaultMessage: 'Change external incident management system',
+});
diff --git a/x-pack/plugins/observability/public/components/app/cases/wrappers/index.tsx b/x-pack/plugins/observability/public/components/app/cases/wrappers/index.tsx
new file mode 100644
index 0000000000000..477fb77d98ee8
--- /dev/null
+++ b/x-pack/plugins/observability/public/components/app/cases/wrappers/index.tsx
@@ -0,0 +1,21 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import styled from 'styled-components';
+
+export const WhitePageWrapper = styled.div`
+  background-color: ${({ theme }) => theme.eui.euiColorEmptyShade};
+  border-top: ${({ theme }) => theme.eui.euiBorderThin};
+  flex: 1 1 auto;
+`;
+
+export const SectionWrapper = styled.div`
+  box-sizing: content-box;
+  margin: 0 auto;
+  max-width: 1175px;
+  width: 100%;
+`;
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/field_formats.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/field_formats.ts
index f1fc5f310b8ef..25f258e17307d 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/field_formats.ts
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/field_formats.ts
@@ -12,6 +12,7 @@ import {
   LCP_FIELD,
   TBT_FIELD,
   TRANSACTION_DURATION,
+  TRANSACTION_TIME_TO_FIRST_BYTE,
 } from '../constants/elasticsearch_fieldnames';
 
 export const rumFieldFormats: FieldFormat[] = [
@@ -24,6 +25,7 @@ export const rumFieldFormats: FieldFormat[] = [
         outputFormat: 'asSeconds',
         showSuffix: true,
         outputPrecision: 1,
+        useShortSuffix: true,
       },
     },
   },
@@ -33,8 +35,9 @@ export const rumFieldFormats: FieldFormat[] = [
       id: 'duration',
       params: {
         inputFormat: 'milliseconds',
-        outputFormat: 'asSeconds',
+        outputFormat: 'humanizePrecise',
         showSuffix: true,
+        useShortSuffix: true,
       },
     },
   },
@@ -44,8 +47,9 @@ export const rumFieldFormats: FieldFormat[] = [
       id: 'duration',
       params: {
         inputFormat: 'milliseconds',
-        outputFormat: 'asSeconds',
+        outputFormat: 'humanizePrecise',
         showSuffix: true,
+        useShortSuffix: true,
       },
     },
   },
@@ -55,8 +59,9 @@ export const rumFieldFormats: FieldFormat[] = [
       id: 'duration',
       params: {
         inputFormat: 'milliseconds',
-        outputFormat: 'asSeconds',
+        outputFormat: 'humanizePrecise',
         showSuffix: true,
+        useShortSuffix: true,
       },
     },
   },
@@ -66,8 +71,21 @@ export const rumFieldFormats: FieldFormat[] = [
       id: 'duration',
       params: {
         inputFormat: 'milliseconds',
-        outputFormat: 'asSeconds',
+        outputFormat: 'humanizePrecise',
+        showSuffix: true,
+        useShortSuffix: true,
+      },
+    },
+  },
+  {
+    field: TRANSACTION_TIME_TO_FIRST_BYTE,
+    format: {
+      id: 'duration',
+      params: {
+        inputFormat: 'milliseconds',
+        outputFormat: 'humanizePrecise',
         showSuffix: true,
+        useShortSuffix: true,
       },
     },
   },
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/kpi_trends_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/kpi_trends_config.ts
index 5e2d3440526b5..f6c683caaa039 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/kpi_trends_config.ts
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/kpi_trends_config.ts
@@ -44,7 +44,7 @@ export function getKPITrendsLensConfig({ seriesId, indexPattern }: ConfigProps):
     id: seriesId,
     defaultSeriesType: 'bar_stacked',
     reportType: 'kpi-trends',
-    seriesTypes: ['bar', 'bar_stacked'],
+    seriesTypes: [],
     xAxisColumn: {
       sourceField: '@timestamp',
     },
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/performance_dist_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/performance_dist_config.ts
index 0dc582c5683dd..4a1521c834806 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/performance_dist_config.ts
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/performance_dist_config.ts
@@ -44,7 +44,7 @@ export function getPerformanceDistLensConfig({ seriesId, indexPattern }: ConfigP
     id: seriesId ?? 'unique-key',
     reportType: 'page-load-dist',
     defaultSeriesType: 'line',
-    seriesTypes: ['line', 'bar'],
+    seriesTypes: [],
     xAxisColumn: {
       sourceField: 'performance.metric',
     },
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/field_formats.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/field_formats.ts
index 8dad1839f0bcd..5c91e3924cbb7 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/field_formats.ts
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/field_formats.ts
@@ -14,9 +14,10 @@ export const syntheticsFieldFormats: FieldFormat[] = [
       id: 'duration',
       params: {
         inputFormat: 'microseconds',
-        outputFormat: 'asMilliseconds',
-        outputPrecision: 0,
+        outputFormat: 'humanizePrecise',
+        outputPrecision: 1,
         showSuffix: true,
+        useShortSuffix: true,
       },
     },
   },
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/monitor_duration_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/monitor_duration_config.ts
index 698b8f9e951e1..5e8a43ccf2ef4 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/monitor_duration_config.ts
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/monitor_duration_config.ts
@@ -15,7 +15,7 @@ export function getMonitorDurationConfig({ seriesId, indexPattern }: ConfigProps
     id: seriesId,
     reportType: 'uptime-duration',
     defaultSeriesType: 'line',
-    seriesTypes: ['line', 'bar_stacked'],
+    seriesTypes: [],
     xAxisColumn: {
       sourceField: '@timestamp',
     },
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/monitor_pings_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/monitor_pings_config.ts
index fc33c37c7bcad..697a940f666f7 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/monitor_pings_config.ts
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/monitor_pings_config.ts
@@ -15,7 +15,7 @@ export function getMonitorPingsConfig({ seriesId, indexPattern }: ConfigProps):
     id: seriesId,
     reportType: 'uptime-pings',
     defaultSeriesType: 'bar_stacked',
-    seriesTypes: ['bar_stacked', 'bar'],
+    seriesTypes: [],
     xAxisColumn: {
       sourceField: '@timestamp',
     },
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts
index c3dd824e441a8..87772532f410d 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts
@@ -108,13 +108,14 @@ export type AppDataType = 'synthetics' | 'ux' | 'infra_logs' | 'infra_metrics' |
 
 type FormatType = 'duration' | 'number';
 type InputFormat = 'microseconds' | 'milliseconds' | 'seconds';
-type OutputFormat = 'asSeconds' | 'asMilliseconds' | 'humanize';
+type OutputFormat = 'asSeconds' | 'asMilliseconds' | 'humanize' | 'humanizePrecise';
 
 export interface FieldFormatParams {
   inputFormat: InputFormat;
   outputFormat: OutputFormat;
   outputPrecision?: number;
   showSuffix?: boolean;
+  useShortSuffix?: boolean;
 }
 
 export interface FieldFormat {
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.test.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.test.ts
index ade74e7c6744e..a8c5c1a0a3b79 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.test.ts
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.test.ts
@@ -17,23 +17,53 @@ const fieldFormats = {
       outputFormat: 'asSeconds',
       outputPrecision: 1,
       showSuffix: true,
+      useShortSuffix: true,
     },
   },
   'transaction.experience.fid': {
     id: 'duration',
-    params: { inputFormat: 'milliseconds', outputFormat: 'asSeconds', showSuffix: true },
+    params: {
+      inputFormat: 'milliseconds',
+      outputFormat: 'humanizePrecise',
+      showSuffix: true,
+      useShortSuffix: true,
+    },
   },
   'transaction.experience.tbt': {
     id: 'duration',
-    params: { inputFormat: 'milliseconds', outputFormat: 'asSeconds', showSuffix: true },
+    params: {
+      inputFormat: 'milliseconds',
+      outputFormat: 'humanizePrecise',
+      showSuffix: true,
+      useShortSuffix: true,
+    },
   },
   'transaction.marks.agent.firstContentfulPaint': {
     id: 'duration',
-    params: { inputFormat: 'milliseconds', outputFormat: 'asSeconds', showSuffix: true },
+    params: {
+      inputFormat: 'milliseconds',
+      outputFormat: 'humanizePrecise',
+      showSuffix: true,
+      useShortSuffix: true,
+    },
   },
   'transaction.marks.agent.largestContentfulPaint': {
     id: 'duration',
-    params: { inputFormat: 'milliseconds', outputFormat: 'asSeconds', showSuffix: true },
+    params: {
+      inputFormat: 'milliseconds',
+      outputFormat: 'humanizePrecise',
+      showSuffix: true,
+      useShortSuffix: true,
+    },
+  },
+  'transaction.marks.agent.timeToFirstByte': {
+    id: 'duration',
+    params: {
+      inputFormat: 'milliseconds',
+      outputFormat: 'humanizePrecise',
+      showSuffix: true,
+      useShortSuffix: true,
+    },
   },
 };
 
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.ts
index c265bad56e864..858eb52555da6 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.ts
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.ts
@@ -60,6 +60,7 @@ export function isParamsSame(param1: IFieldFormat['_params'], param2: FieldForma
   const isSame =
     param1?.inputFormat === param2?.inputFormat &&
     param1?.outputFormat === param2?.outputFormat &&
+    param1?.useShortSuffix === param2?.useShortSuffix &&
     param1?.showSuffix === param2?.showSuffix;
 
   if (param2.outputPrecision !== undefined) {
diff --git a/x-pack/plugins/observability/public/hooks/use_breadcrumbs.ts b/x-pack/plugins/observability/public/hooks/use_breadcrumbs.ts
index d31b6b52744c0..090031e314fd1 100644
--- a/x-pack/plugins/observability/public/hooks/use_breadcrumbs.ts
+++ b/x-pack/plugins/observability/public/hooks/use_breadcrumbs.ts
@@ -9,8 +9,8 @@ import { ChromeBreadcrumb } from 'kibana/public';
 import { i18n } from '@kbn/i18n';
 import { MouseEvent, useEffect } from 'react';
 import { EuiBreadcrumb } from '@elastic/eui';
-import { useKibana } from '../../../../../src/plugins/kibana_react/public';
 import { useQueryParams } from './use_query_params';
+import { useKibana } from '../utils/kibana_react';
 
 function handleBreadcrumbClick(
   breadcrumbs: ChromeBreadcrumb[],
@@ -39,17 +39,35 @@ export const makeBaseBreadcrumb = (href: string): EuiBreadcrumb => {
     href,
   };
 };
-
+export const casesBreadcrumbs = {
+  cases: {
+    text: i18n.translate('xpack.observability.breadcrumbs.observability.cases', {
+      defaultMessage: 'Cases',
+    }),
+  },
+  create: {
+    text: i18n.translate('xpack.observability.breadcrumbs.observability.cases.create', {
+      defaultMessage: 'Create',
+    }),
+  },
+  configure: {
+    text: i18n.translate('xpack.observability.breadcrumbs.observability.cases.configure', {
+      defaultMessage: 'Configure',
+    }),
+  },
+};
 export const useBreadcrumbs = (extraCrumbs: ChromeBreadcrumb[]) => {
   const params = useQueryParams();
 
   const {
-    services: { chrome, application },
+    services: {
+      chrome: { setBreadcrumbs },
+      application: { getUrlForApp, navigateToUrl },
+    },
   } = useKibana();
 
-  const setBreadcrumbs = chrome?.setBreadcrumbs;
-  const appPath = application?.getUrlForApp('observability-overview') ?? '';
-  const navigate = application?.navigateToUrl;
+  const appPath = getUrlForApp('observability-overview') ?? '';
+  const navigate = navigateToUrl;
 
   useEffect(() => {
     if (setBreadcrumbs) {
diff --git a/x-pack/plugins/observability/public/hooks/use_get_user_cases_permissions.tsx b/x-pack/plugins/observability/public/hooks/use_get_user_cases_permissions.tsx
new file mode 100644
index 0000000000000..9f4ed59a45f2b
--- /dev/null
+++ b/x-pack/plugins/observability/public/hooks/use_get_user_cases_permissions.tsx
@@ -0,0 +1,37 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { useEffect, useState } from 'react';
+import { useKibana } from '../utils/kibana_react';
+import { CASES_APP_ID } from '../../common/const';
+
+export interface UseGetUserCasesPermissions {
+  crud: boolean;
+  read: boolean;
+}
+
+export function useGetUserCasesPermissions() {
+  const [casesPermissions, setCasesPermissions] = useState<UseGetUserCasesPermissions | null>(null);
+  const uiCapabilities = useKibana().services.application.capabilities;
+
+  useEffect(() => {
+    const capabilitiesCanUserCRUD: boolean =
+      typeof uiCapabilities[CASES_APP_ID].crud_cases === 'boolean'
+        ? (uiCapabilities[CASES_APP_ID].crud_cases as boolean)
+        : false;
+    const capabilitiesCanUserRead: boolean =
+      typeof uiCapabilities[CASES_APP_ID].read_cases === 'boolean'
+        ? (uiCapabilities[CASES_APP_ID].read_cases as boolean)
+        : false;
+    setCasesPermissions({
+      crud: capabilitiesCanUserCRUD,
+      read: capabilitiesCanUserRead,
+    });
+  }, [uiCapabilities]);
+
+  return casesPermissions;
+}
diff --git a/x-pack/plugins/observability/public/hooks/use_messages_storage.tsx b/x-pack/plugins/observability/public/hooks/use_messages_storage.tsx
new file mode 100644
index 0000000000000..d67910f00dc76
--- /dev/null
+++ b/x-pack/plugins/observability/public/hooks/use_messages_storage.tsx
@@ -0,0 +1,66 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { useCallback } from 'react';
+import { useKibana } from '../utils/kibana_react';
+
+export interface UseMessagesStorage {
+  getMessages: (plugin: string) => string[];
+  addMessage: (plugin: string, id: string) => void;
+  removeMessage: (plugin: string, id: string) => void;
+  clearAllMessages: (plugin: string) => void;
+  hasMessage: (plugin: string, id: string) => boolean;
+}
+
+export const useMessagesStorage = (): UseMessagesStorage => {
+  const { storage } = useKibana().services;
+
+  const getMessages = useCallback(
+    (plugin: string): string[] => storage.get(`${plugin}-messages`) ?? [],
+    [storage]
+  );
+
+  const addMessage = useCallback(
+    (plugin: string, id: string) => {
+      const pluginStorage = storage.get(`${plugin}-messages`) ?? [];
+      storage.set(`${plugin}-messages`, [...pluginStorage, id]);
+    },
+    [storage]
+  );
+
+  const hasMessage = useCallback(
+    (plugin: string, id: string): boolean => {
+      const pluginStorage = storage.get(`${plugin}-messages`) ?? [];
+      return pluginStorage.includes((val: string) => val === id);
+    },
+    [storage]
+  );
+
+  const removeMessage = useCallback(
+    (plugin: string, id: string) => {
+      const pluginStorage = storage.get(`${plugin}-messages`) ?? [];
+      storage.set(
+        `${plugin}-messages`,
+        pluginStorage.filter((val: string) => val !== id)
+      );
+    },
+    [storage]
+  );
+
+  const clearAllMessages = useCallback(
+    (plugin: string): string[] => storage.remove(`${plugin}-messages`),
+    [storage]
+  );
+
+  return {
+    getMessages,
+    addMessage,
+    clearAllMessages,
+    removeMessage,
+    hasMessage,
+  };
+};
diff --git a/x-pack/plugins/observability/public/pages/cases/all_cases.tsx b/x-pack/plugins/observability/public/pages/cases/all_cases.tsx
new file mode 100644
index 0000000000000..4131cdc40738f
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/cases/all_cases.tsx
@@ -0,0 +1,42 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { AllCases } from '../../components/app/cases/all_cases';
+import * as i18n from '../../components/app/cases/translations';
+
+import { permissionsReadOnlyErrorMessage, CaseCallOut } from '../../components/app/cases/callout';
+import { CaseFeatureNoPermissions } from './feature_no_permissions';
+import { useGetUserCasesPermissions } from '../../hooks/use_get_user_cases_permissions';
+import { usePluginContext } from '../../hooks/use_plugin_context';
+
+export const AllCasesPage = React.memo(() => {
+  const userPermissions = useGetUserCasesPermissions();
+  const { ObservabilityPageTemplate } = usePluginContext();
+  return userPermissions == null || userPermissions?.read ? (
+    <>
+      {userPermissions != null && !userPermissions?.crud && userPermissions?.read && (
+        <CaseCallOut
+          title={permissionsReadOnlyErrorMessage.title}
+          messages={[{ ...permissionsReadOnlyErrorMessage, title: '' }]}
+        />
+      )}
+      <ObservabilityPageTemplate
+        pageHeader={{
+          pageTitle: <>{i18n.PAGE_TITLE}</>,
+        }}
+      >
+        <AllCases userCanCrud={userPermissions?.crud ?? false} />
+      </ObservabilityPageTemplate>
+    </>
+  ) : (
+    <CaseFeatureNoPermissions />
+  );
+});
+
+AllCasesPage.displayName = 'AllCasesPage';
diff --git a/x-pack/plugins/observability/public/pages/cases/case_details.tsx b/x-pack/plugins/observability/public/pages/cases/case_details.tsx
new file mode 100644
index 0000000000000..78f1cb313ea9b
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/cases/case_details.tsx
@@ -0,0 +1,49 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { useParams } from 'react-router-dom';
+
+import { CaseView } from '../../components/app/cases/case_view';
+import { useGetUserCasesPermissions } from '../../hooks/use_get_user_cases_permissions';
+import { useKibana } from '../../utils/kibana_react';
+import { CASES_APP_ID } from '../../components/app/cases/constants';
+import { CaseCallOut, permissionsReadOnlyErrorMessage } from '../../components/app/cases/callout';
+
+export const CaseDetailsPage = React.memo(() => {
+  const {
+    application: { navigateToApp },
+  } = useKibana().services;
+  const userPermissions = useGetUserCasesPermissions();
+  const { detailName: caseId, subCaseId } = useParams<{
+    detailName?: string;
+    subCaseId?: string;
+  }>();
+
+  if (userPermissions != null && !userPermissions.read) {
+    navigateToApp(`${CASES_APP_ID}`);
+    return null;
+  }
+
+  return caseId != null ? (
+    <>
+      {userPermissions != null && !userPermissions?.crud && userPermissions?.read && (
+        <CaseCallOut
+          title={permissionsReadOnlyErrorMessage.title}
+          messages={[{ ...permissionsReadOnlyErrorMessage, title: '' }]}
+        />
+      )}
+      <CaseView
+        caseId={caseId}
+        subCaseId={subCaseId}
+        userCanCrud={userPermissions?.crud ?? false}
+      />
+    </>
+  ) : null;
+});
+
+CaseDetailsPage.displayName = 'CaseDetailsPage';
diff --git a/x-pack/plugins/observability/public/pages/cases/cases.stories.tsx b/x-pack/plugins/observability/public/pages/cases/cases.stories.tsx
index 49df932766b33..13d8795193238 100644
--- a/x-pack/plugins/observability/public/pages/cases/cases.stories.tsx
+++ b/x-pack/plugins/observability/public/pages/cases/cases.stories.tsx
@@ -6,12 +6,11 @@
  */
 
 import React, { ComponentType } from 'react';
-import { CasesPage } from '.';
-import { RouteParams } from '../../routes';
+import { AllCasesPage } from './all_cases';
 
 export default {
   title: 'app/Cases',
-  component: CasesPage,
+  component: AllCasesPage,
   decorators: [
     (Story: ComponentType) => {
       return <Story />;
@@ -20,5 +19,5 @@ export default {
 };
 
 export function EmptyState() {
-  return <CasesPage routeParams={{} as RouteParams<'/cases'>} />;
+  return <AllCasesPage />;
 }
diff --git a/x-pack/plugins/observability/public/pages/cases/configure_cases.tsx b/x-pack/plugins/observability/public/pages/cases/configure_cases.tsx
new file mode 100644
index 0000000000000..acc6bdf68fba7
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/cases/configure_cases.tsx
@@ -0,0 +1,71 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { useCallback } from 'react';
+import styled from 'styled-components';
+
+import { EuiButtonEmpty } from '@elastic/eui';
+import * as i18n from '../../components/app/cases/translations';
+import { CASES_APP_ID, CASES_OWNER } from '../../components/app/cases/constants';
+import { useKibana } from '../../utils/kibana_react';
+import { useGetUserCasesPermissions } from '../../hooks/use_get_user_cases_permissions';
+import { usePluginContext } from '../../hooks/use_plugin_context';
+import { casesBreadcrumbs, useBreadcrumbs } from '../../hooks/use_breadcrumbs';
+import { getCaseUrl, useFormatUrl } from './links';
+
+const ButtonEmpty = styled(EuiButtonEmpty)`
+  display: block;
+`;
+function ConfigureCasesPageComponent() {
+  const {
+    cases,
+    application: { navigateToApp },
+  } = useKibana().services;
+  const userPermissions = useGetUserCasesPermissions();
+  const { ObservabilityPageTemplate } = usePluginContext();
+  const onClickGoToCases = useCallback(
+    async (ev) => {
+      ev.preventDefault();
+      return navigateToApp(`${CASES_APP_ID}`);
+    },
+    [navigateToApp]
+  );
+  const { formatUrl } = useFormatUrl(CASES_APP_ID);
+  const href = formatUrl(getCaseUrl());
+  useBreadcrumbs([{ ...casesBreadcrumbs.cases, href }, casesBreadcrumbs.configure]);
+  if (userPermissions != null && !userPermissions.read) {
+    navigateToApp(`${CASES_APP_ID}`);
+    return null;
+  }
+
+  return (
+    <ObservabilityPageTemplate
+      pageHeader={{
+        pageTitle: (
+          <>
+            <ButtonEmpty
+              onClick={onClickGoToCases}
+              iconType="arrowLeft"
+              iconSide="left"
+              flush="left"
+            >
+              {i18n.BACK_TO_ALL}
+            </ButtonEmpty>
+            {i18n.CONFIGURE_CASES_PAGE_TITLE}
+          </>
+        ),
+      }}
+    >
+      {cases.getConfigureCases({
+        userCanCrud: userPermissions?.crud ?? false,
+        owner: [CASES_OWNER],
+      })}
+    </ObservabilityPageTemplate>
+  );
+}
+
+export const ConfigureCasesPage = React.memo(ConfigureCasesPageComponent);
diff --git a/x-pack/plugins/observability/public/pages/cases/create_case.tsx b/x-pack/plugins/observability/public/pages/cases/create_case.tsx
new file mode 100644
index 0000000000000..d0e25e6263075
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/cases/create_case.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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { useCallback } from 'react';
+import { EuiButtonEmpty } from '@elastic/eui';
+import styled from 'styled-components';
+import * as i18n from '../../components/app/cases/translations';
+import { Create } from '../../components/app/cases/create';
+import { CASES_APP_ID } from '../../components/app/cases/constants';
+import { useKibana } from '../../utils/kibana_react';
+import { useGetUserCasesPermissions } from '../../hooks/use_get_user_cases_permissions';
+import { usePluginContext } from '../../hooks/use_plugin_context';
+import { getCaseUrl, useFormatUrl } from './links';
+import { casesBreadcrumbs, useBreadcrumbs } from '../../hooks/use_breadcrumbs';
+
+const ButtonEmpty = styled(EuiButtonEmpty)`
+  display: block;
+`;
+ButtonEmpty.displayName = 'ButtonEmpty';
+export const CreateCasePage = React.memo(() => {
+  const userPermissions = useGetUserCasesPermissions();
+  const { ObservabilityPageTemplate } = usePluginContext();
+  const {
+    application: { navigateToApp },
+  } = useKibana().services;
+
+  const goTo = useCallback(
+    async (ev) => {
+      ev.preventDefault();
+      return navigateToApp(CASES_APP_ID);
+    },
+    [navigateToApp]
+  );
+
+  const { formatUrl } = useFormatUrl(CASES_APP_ID);
+  const href = formatUrl(getCaseUrl());
+  useBreadcrumbs([{ ...casesBreadcrumbs.cases, href }, casesBreadcrumbs.create]);
+  if (userPermissions != null && !userPermissions.crud) {
+    navigateToApp(`${CASES_APP_ID}`);
+    return null;
+  }
+
+  return (
+    <ObservabilityPageTemplate
+      pageHeader={{
+        pageTitle: (
+          <>
+            <ButtonEmpty onClick={goTo} iconType="arrowLeft" iconSide="left" flush="left">
+              {i18n.BACK_TO_ALL}
+            </ButtonEmpty>
+            {i18n.CREATE_TITLE}
+          </>
+        ),
+      }}
+    >
+      <Create />
+    </ObservabilityPageTemplate>
+  );
+});
+
+CreateCasePage.displayName = 'CreateCasePage';
diff --git a/x-pack/plugins/observability/public/pages/cases/empty_page.tsx b/x-pack/plugins/observability/public/pages/cases/empty_page.tsx
new file mode 100644
index 0000000000000..c6fc4b59ef77c
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/cases/empty_page.tsx
@@ -0,0 +1,118 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import {
+  EuiButton,
+  EuiEmptyPrompt,
+  EuiFlexGroup,
+  EuiFlexItem,
+  IconType,
+  EuiCard,
+} from '@elastic/eui';
+import React, { MouseEventHandler, ReactNode, useMemo } from 'react';
+import styled from 'styled-components';
+
+const EmptyPrompt = styled(EuiEmptyPrompt)`
+  align-self: center; /* Corrects horizontal centering in IE11 */
+  max-width: 60em;
+`;
+
+EmptyPrompt.displayName = 'EmptyPrompt';
+
+interface EmptyPageActions {
+  icon?: IconType;
+  label: string;
+  target?: string;
+  url: string;
+  descriptionTitle?: string;
+  description?: string;
+  fill?: boolean;
+  onClick?: MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>;
+}
+
+export type EmptyPageActionsProps = Record<string, EmptyPageActions>;
+
+interface EmptyPageProps {
+  actions: EmptyPageActionsProps;
+  'data-test-subj'?: string;
+  message?: ReactNode;
+  title: string;
+}
+
+const EmptyPageComponent = React.memo<EmptyPageProps>(({ actions, message, title, ...rest }) => {
+  const titles = Object.keys(actions);
+  const maxItemWidth = 283;
+  const renderActions = useMemo(
+    () =>
+      Object.values(actions)
+        .filter((a) => a.label && a.url)
+        .map(
+          (
+            { icon, label, target, url, descriptionTitle, description, onClick, fill = true },
+            idx
+          ) =>
+            descriptionTitle != null || description != null ? (
+              <EuiFlexItem
+                grow={false}
+                style={{ maxWidth: maxItemWidth }}
+                key={`empty-page-${titles[idx]}-action`}
+              >
+                <EuiCard
+                  title={descriptionTitle ?? false}
+                  description={description ?? false}
+                  footer={
+                    /* eslint-disable-next-line @elastic/eui/href-or-on-click */
+                    <EuiButton
+                      href={url}
+                      onClick={onClick}
+                      iconType={icon}
+                      target={target}
+                      fill={fill}
+                      data-test-subj={`empty-page-${titles[idx]}-action`}
+                    >
+                      {label}
+                    </EuiButton>
+                  }
+                />
+              </EuiFlexItem>
+            ) : (
+              <EuiFlexItem
+                grow={false}
+                style={{ maxWidth: maxItemWidth }}
+                key={`empty-page-${titles[idx]}-action`}
+              >
+                {/* eslint-disable-next-line @elastic/eui/href-or-on-click */}
+                <EuiButton
+                  href={url}
+                  onClick={onClick}
+                  iconType={icon}
+                  target={target}
+                  data-test-subj={`empty-page-${titles[idx]}-action`}
+                >
+                  {label}
+                </EuiButton>
+              </EuiFlexItem>
+            )
+        ),
+    [actions, titles]
+  );
+
+  return (
+    <EmptyPrompt
+      iconType="logoObservability"
+      title={<h2>{title}</h2>}
+      body={message && <p>{message}</p>}
+      actions={<EuiFlexGroup justifyContent="center">{renderActions}</EuiFlexGroup>}
+      {...rest}
+    />
+  );
+});
+
+EmptyPageComponent.displayName = 'EmptyPageComponent';
+
+export const EmptyPage = React.memo(EmptyPageComponent);
+EmptyPage.displayName = 'EmptyPage';
diff --git a/x-pack/plugins/observability/public/pages/cases/feature_no_permissions.tsx b/x-pack/plugins/observability/public/pages/cases/feature_no_permissions.tsx
new file mode 100644
index 0000000000000..5075570c15b3e
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/cases/feature_no_permissions.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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { useMemo } from 'react';
+
+import { EmptyPage } from './empty_page';
+import * as i18n from '../../components/app/cases/translations';
+import { useKibana } from '../../utils/kibana_react';
+
+export const CaseFeatureNoPermissions = React.memo(() => {
+  const docLinks = useKibana().services.docLinks;
+  const actions = useMemo(
+    () => ({
+      savedObject: {
+        icon: 'documents',
+        label: i18n.GO_TO_DOCUMENTATION,
+        url: `${docLinks.ELASTIC_WEBSITE_URL}guide/en/security/${docLinks.DOC_LINK_VERSION}s`,
+        target: '_blank',
+      },
+    }),
+    [docLinks]
+  );
+
+  return (
+    <EmptyPage
+      actions={actions}
+      message={i18n.CASES_FEATURE_NO_PERMISSIONS_MSG}
+      data-test-subj="no_feature_permissions"
+      title={i18n.CASES_FEATURE_NO_PERMISSIONS_TITLE}
+    />
+  );
+});
+
+CaseFeatureNoPermissions.displayName = 'CaseSavedObjectNoPermissions';
diff --git a/x-pack/plugins/observability/public/pages/cases/index.tsx b/x-pack/plugins/observability/public/pages/cases/index.tsx
deleted file mode 100644
index 7f6bce7d486f3..0000000000000
--- a/x-pack/plugins/observability/public/pages/cases/index.tsx
+++ /dev/null
@@ -1,51 +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
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { EuiCallOut, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
-import React from 'react';
-import { ExperimentalBadge } from '../../components/shared/experimental_badge';
-import { RouteParams } from '../../routes';
-import { usePluginContext } from '../../hooks/use_plugin_context';
-
-interface CasesProps {
-  routeParams: RouteParams<'/cases'>;
-}
-
-export function CasesPage(props: CasesProps) {
-  const { ObservabilityPageTemplate } = usePluginContext();
-  return (
-    <ObservabilityPageTemplate
-      pageHeader={{
-        pageTitle: (
-          <>
-            {i18n.translate('xpack.observability.casesTitle', { defaultMessage: 'Cases' })}{' '}
-            <ExperimentalBadge />
-          </>
-        ),
-      }}
-    >
-      <EuiFlexGroup direction="column">
-        <EuiFlexItem>
-          <EuiCallOut
-            title={i18n.translate('xpack.observability.casesDisclaimerTitle', {
-              defaultMessage: 'Coming soon',
-            })}
-            color="warning"
-            iconType="beaker"
-          >
-            <p>
-              {i18n.translate('xpack.observability.casesDisclaimerText', {
-                defaultMessage: 'This is the future home of cases.',
-              })}
-            </p>
-          </EuiCallOut>
-        </EuiFlexItem>
-      </EuiFlexGroup>
-    </ObservabilityPageTemplate>
-  );
-}
diff --git a/x-pack/plugins/observability/public/pages/cases/links.ts b/x-pack/plugins/observability/public/pages/cases/links.ts
new file mode 100644
index 0000000000000..768d74ec4e7ee
--- /dev/null
+++ b/x-pack/plugins/observability/public/pages/cases/links.ts
@@ -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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { useCallback } from 'react';
+import { isEmpty } from 'lodash/fp';
+import { useKibana } from '../../utils/kibana_react';
+
+export const getCaseDetailsUrl = ({ id, subCaseId }: { id: string; subCaseId?: string }) => {
+  if (subCaseId) {
+    return `/${encodeURIComponent(id)}/sub-cases/${encodeURIComponent(subCaseId)}`;
+  }
+  return `/${encodeURIComponent(id)}`;
+};
+interface FormatUrlOptions {
+  absolute: boolean;
+}
+
+export type FormatUrl = (path: string, options?: Partial<FormatUrlOptions>) => string;
+export const useFormatUrl = (appId: string) => {
+  const { getUrlForApp } = useKibana().services.application;
+  const formatUrl = useCallback<FormatUrl>(
+    (path: string, { absolute = false } = {}) => {
+      const pathArr = path.split('?');
+      const formattedPath = `${pathArr[0]}${isEmpty(pathArr[1]) ? '' : `?${pathArr[1]}`}`;
+      return getUrlForApp(`${appId}`, {
+        path: formattedPath,
+        absolute,
+      });
+    },
+    [appId, getUrlForApp]
+  );
+  return { formatUrl };
+};
+
+export const getCaseDetailsUrlWithCommentId = ({
+  id,
+  commentId,
+  subCaseId,
+}: {
+  id: string;
+  commentId: string;
+  subCaseId?: string;
+}) => {
+  if (subCaseId) {
+    return `/${encodeURIComponent(id)}/sub-cases/${encodeURIComponent(
+      subCaseId
+    )}/${encodeURIComponent(commentId)}`;
+  }
+  return `/${encodeURIComponent(id)}/${encodeURIComponent(commentId)}`;
+};
+
+export const getCreateCaseUrl = () => `/create`;
+
+export const getConfigureCasesUrl = () => `/configure`;
+export const getCaseUrl = () => `/`;
diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts
index c1b18e37faee8..03c3fb3c27e58 100644
--- a/x-pack/plugins/observability/public/plugin.ts
+++ b/x-pack/plugins/observability/public/plugin.ts
@@ -36,6 +36,8 @@ import { toggleOverviewLinkInNav } from './toggle_overview_link_in_nav';
 import { ConfigSchema } from '.';
 import { createObservabilityRuleTypeRegistry } from './rules/create_observability_rule_type_registry';
 import { createLazyObservabilityPageTemplate } from './components/shared';
+import { CASES_APP_ID } from './components/app/cases/constants';
+import { CasesUiStart } from '../../cases/public';
 
 export type ObservabilityPublicSetup = ReturnType<Plugin['setup']>;
 
@@ -46,6 +48,7 @@ export interface ObservabilityPublicPluginsSetup {
 }
 
 export interface ObservabilityPublicPluginsStart {
+  cases: CasesUiStart;
   home?: HomePublicPluginStart;
   triggersActionsUi: TriggersAndActionsUIPublicPluginStart;
   data: DataPublicPluginStart;
@@ -63,6 +66,7 @@ export class Plugin
       ObservabilityPublicPluginsStart
     > {
   private readonly appUpdater$ = new BehaviorSubject<AppUpdater>(() => ({}));
+  private readonly casesAppUpdater$ = new BehaviorSubject<AppUpdater>(() => ({}));
   private readonly navigationRegistry = createNavigationRegistry();
 
   constructor(private readonly initializerContext: PluginInitializerContext<ConfigSchema>) {
@@ -111,7 +115,6 @@ export class Plugin
       mount,
       updater$,
     });
-
     if (config.unsafe.alertingExperience.enabled) {
       coreSetup.application.register({
         id: 'observability-alerts',
@@ -127,14 +130,14 @@ export class Plugin
 
     if (config.unsafe.cases.enabled) {
       coreSetup.application.register({
-        id: 'observability-cases',
+        id: CASES_APP_ID,
         title: 'Cases',
         appRoute: '/app/observability/cases',
         order: 8050,
         category,
         euiIconType,
         mount,
-        updater$,
+        updater$: this.casesAppUpdater$,
       });
     }
 
@@ -188,7 +191,7 @@ export class Plugin
     };
   }
   public start({ application }: CoreStart) {
-    toggleOverviewLinkInNav(this.appUpdater$, application);
+    toggleOverviewLinkInNav(this.appUpdater$, this.casesAppUpdater$, application);
 
     const PageTemplate = createLazyObservabilityPageTemplate({
       currentAppId$: application.currentAppId$,
diff --git a/x-pack/plugins/observability/public/routes/index.tsx b/x-pack/plugins/observability/public/routes/index.tsx
index 6e180347106d6..a2a67a42bd166 100644
--- a/x-pack/plugins/observability/public/routes/index.tsx
+++ b/x-pack/plugins/observability/public/routes/index.tsx
@@ -13,8 +13,12 @@ import { LandingPage } from '../pages/landing';
 import { OverviewPage } from '../pages/overview';
 import { jsonRt } from './json_rt';
 import { AlertsPage } from '../pages/alerts';
-import { CasesPage } from '../pages/cases';
+import { CreateCasePage } from '../pages/cases/create_case';
 import { ExploratoryViewPage } from '../components/shared/exploratory_view';
+import { CaseDetailsPage } from '../pages/cases/case_details';
+import { ConfigureCasesPage } from '../pages/cases/configure_cases';
+import { AllCasesPage } from '../pages/cases/all_cases';
+import { casesBreadcrumbs } from '../hooks/use_breadcrumbs';
 import { alertStatusRt } from '../../common/typings';
 
 export type RouteParams<T extends keyof typeof routes> = DecodeParams<typeof routes[T]['params']>;
@@ -78,24 +82,36 @@ export const routes = {
     ],
   },
   '/cases': {
-    handler: (routeParams: any) => {
-      return <CasesPage routeParams={routeParams} />;
+    handler: () => {
+      return <AllCasesPage />;
+    },
+    params: {},
+    breadcrumb: [casesBreadcrumbs.cases],
+  },
+  '/cases/create': {
+    handler: () => {
+      return <CreateCasePage />;
+    },
+    params: {},
+    breadcrumb: [casesBreadcrumbs.cases, casesBreadcrumbs.create],
+  },
+  '/cases/configure': {
+    handler: () => {
+      return <ConfigureCasesPage />;
+    },
+    params: {},
+    breadcrumb: [casesBreadcrumbs.cases, casesBreadcrumbs.configure],
+  },
+  '/cases/:detailName': {
+    handler: () => {
+      return <CaseDetailsPage />;
     },
     params: {
-      query: t.partial({
-        rangeFrom: t.string,
-        rangeTo: t.string,
-        refreshPaused: jsonRt.pipe(t.boolean),
-        refreshInterval: jsonRt.pipe(t.number),
+      path: t.partial({
+        detailName: t.string,
       }),
     },
-    breadcrumb: [
-      {
-        text: i18n.translate('xpack.observability.cases.breadcrumb', {
-          defaultMessage: 'Cases',
-        }),
-      },
-    ],
+    breadcrumb: [casesBreadcrumbs.cases],
   },
   '/alerts': {
     handler: (routeParams: any) => {
diff --git a/x-pack/plugins/observability/public/toggle_overview_link_in_nav.test.tsx b/x-pack/plugins/observability/public/toggle_overview_link_in_nav.test.tsx
index bbcc12b483183..caee692ced2c5 100644
--- a/x-pack/plugins/observability/public/toggle_overview_link_in_nav.test.tsx
+++ b/x-pack/plugins/observability/public/toggle_overview_link_in_nav.test.tsx
@@ -14,6 +14,7 @@ import { toggleOverviewLinkInNav } from './toggle_overview_link_in_nav';
 describe('toggleOverviewLinkInNav', () => {
   let applicationStart: ReturnType<typeof applicationServiceMock.createStartContract>;
   let subjectMock: jest.Mocked<Subject<AppUpdater>>;
+  let casesMock: jest.Mocked<Subject<AppUpdater>>;
 
   beforeEach(() => {
     applicationStart = applicationServiceMock.createStartContract();
@@ -34,7 +35,7 @@ describe('toggleOverviewLinkInNav', () => {
       },
     };
 
-    toggleOverviewLinkInNav(subjectMock, applicationStart);
+    toggleOverviewLinkInNav(subjectMock, casesMock, applicationStart);
 
     expect(subjectMock.next).toHaveBeenCalledTimes(1);
     const updater = subjectMock.next.mock.calls[0][0]!;
@@ -54,7 +55,7 @@ describe('toggleOverviewLinkInNav', () => {
       },
     };
 
-    toggleOverviewLinkInNav(subjectMock, applicationStart);
+    toggleOverviewLinkInNav(subjectMock, casesMock, applicationStart);
 
     expect(subjectMock.next).not.toHaveBeenCalled();
   });
diff --git a/x-pack/plugins/observability/public/toggle_overview_link_in_nav.tsx b/x-pack/plugins/observability/public/toggle_overview_link_in_nav.tsx
index 5110db15def88..fd30bf3b73f15 100644
--- a/x-pack/plugins/observability/public/toggle_overview_link_in_nav.tsx
+++ b/x-pack/plugins/observability/public/toggle_overview_link_in_nav.tsx
@@ -7,13 +7,22 @@
 
 import { Subject } from 'rxjs';
 import { AppNavLinkStatus, AppUpdater, ApplicationStart } from '../../../../src/core/public';
+import { CASES_APP_ID } from '../common/const';
 
 export function toggleOverviewLinkInNav(
   updater$: Subject<AppUpdater>,
+  casesUpdater$: Subject<AppUpdater>,
   { capabilities }: ApplicationStart
 ) {
-  const { apm, logs, metrics, uptime } = capabilities.navLinks;
+  const { apm, logs, metrics, uptime, [CASES_APP_ID]: cases } = capabilities.navLinks;
   const someVisible = Object.values({ apm, logs, metrics, uptime }).some((visible) => visible);
+
+  // if cases is enabled then we want to show it in the sidebar but not the navigation unless one of the other features
+  // is enabled
+  if (cases) {
+    casesUpdater$.next(() => ({ navLinkStatus: AppNavLinkStatus.visible }));
+  }
+
   if (!someVisible) {
     updater$.next(() => ({
       navLinkStatus: AppNavLinkStatus.hidden,
diff --git a/x-pack/plugins/observability/public/utils/kibana_react.ts b/x-pack/plugins/observability/public/utils/kibana_react.ts
new file mode 100644
index 0000000000000..532003e30a160
--- /dev/null
+++ b/x-pack/plugins/observability/public/utils/kibana_react.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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { CoreStart } from 'kibana/public';
+import { useKibana } from '../../../../../src/plugins/kibana_react/public';
+import { Storage } from '../../../../../src/plugins/kibana_utils/public';
+import { ObservabilityPublicPluginsStart } from '../plugin';
+
+export type StartServices = CoreStart &
+  ObservabilityPublicPluginsStart & {
+    storage: Storage;
+  };
+const useTypedKibana = () => useKibana<StartServices>();
+
+export { useTypedKibana as useKibana };
diff --git a/x-pack/plugins/observability/server/plugin.ts b/x-pack/plugins/observability/server/plugin.ts
index 9eff1b08cead9..cfcaeb25d29e4 100644
--- a/x-pack/plugins/observability/server/plugin.ts
+++ b/x-pack/plugins/observability/server/plugin.ts
@@ -5,7 +5,13 @@
  * 2.0.
  */
 
-import { PluginInitializerContext, Plugin, CoreSetup } from 'src/core/server';
+import { i18n } from '@kbn/i18n';
+import {
+  PluginInitializerContext,
+  Plugin,
+  CoreSetup,
+  DEFAULT_APP_CATEGORIES,
+} from '../../../../src/core/server';
 import { RuleDataClient } from '../../rule_registry/server';
 import { ObservabilityConfig } from '.';
 import {
@@ -14,23 +20,65 @@ import {
   AnnotationsAPI,
 } from './lib/annotations/bootstrap_annotations';
 import type { RuleRegistryPluginSetupContract } from '../../rule_registry/server';
+import { PluginSetupContract as FeaturesSetup } from '../../features/server';
 import { uiSettings } from './ui_settings';
 import { registerRoutes } from './routes/register_routes';
 import { getGlobalObservabilityServerRouteRepository } from './routes/get_global_observability_server_route_repository';
+import { CASES_APP_ID, OBSERVABILITY } from '../common/const';
 
 export type ObservabilityPluginSetup = ReturnType<ObservabilityPlugin['setup']>;
 
+interface PluginSetup {
+  features: FeaturesSetup;
+  ruleRegistry: RuleRegistryPluginSetupContract;
+}
+
 export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> {
   constructor(private readonly initContext: PluginInitializerContext) {
     this.initContext = initContext;
   }
 
-  public setup(
-    core: CoreSetup,
-    plugins: {
-      ruleRegistry: RuleRegistryPluginSetupContract;
-    }
-  ) {
+  public setup(core: CoreSetup, plugins: PluginSetup) {
+    plugins.features.registerKibanaFeature({
+      id: CASES_APP_ID,
+      name: i18n.translate('xpack.observability.featureRegistry.linkObservabilityTitle', {
+        defaultMessage: 'Cases',
+      }),
+      order: 1100,
+      category: DEFAULT_APP_CATEGORIES.observability,
+      app: [CASES_APP_ID, 'kibana'],
+      catalogue: [OBSERVABILITY],
+      cases: [OBSERVABILITY],
+      privileges: {
+        all: {
+          app: [CASES_APP_ID, 'kibana'],
+          catalogue: [OBSERVABILITY],
+          cases: {
+            all: [OBSERVABILITY],
+          },
+          api: [],
+          savedObject: {
+            all: [],
+            read: [],
+          },
+          ui: ['crud_cases', 'read_cases'], // uiCapabilities[CASES_APP_ID].crud_cases or read_cases
+        },
+        read: {
+          app: [CASES_APP_ID, 'kibana'],
+          catalogue: [OBSERVABILITY],
+          cases: {
+            read: [OBSERVABILITY],
+          },
+          api: [],
+          savedObject: {
+            all: [],
+            read: [],
+          },
+          ui: ['read_cases'], // uiCapabilities[uiCapabilities[CASES_APP_ID]].read_cases
+        },
+      },
+    });
+
     const config = this.initContext.config.get<ObservabilityConfig>();
 
     let annotationsApiPromise: Promise<AnnotationsAPI> | undefined;
diff --git a/x-pack/plugins/observability/tsconfig.json b/x-pack/plugins/observability/tsconfig.json
index 814d55bfd61fb..b6ed0a0a3d17f 100644
--- a/x-pack/plugins/observability/tsconfig.json
+++ b/x-pack/plugins/observability/tsconfig.json
@@ -24,6 +24,7 @@
     { "path": "../../../src/plugins/usage_collection/tsconfig.json" },
     { "path": "../alerting/tsconfig.json" },
     { "path": "../licensing/tsconfig.json" },
+    { "path": "../cases/tsconfig.json" },
     { "path": "../lens/tsconfig.json" },
     { "path": "../rule_registry/tsconfig.json" },
     { "path": "../translations/tsconfig.json" }
diff --git a/x-pack/plugins/security/common/index.ts b/x-pack/plugins/security/common/index.ts
index 034c25758a1f0..ac5d252c98a8b 100644
--- a/x-pack/plugins/security/common/index.ts
+++ b/x-pack/plugins/security/common/index.ts
@@ -5,5 +5,5 @@
  * 2.0.
  */
 
-export { SecurityLicense } from './licensing';
-export { AuthenticatedUser } from './model';
+export type { SecurityLicense } from './licensing';
+export type { AuthenticatedUser } from './model';
diff --git a/x-pack/plugins/security/public/account_management/change_password/change_password.tsx b/x-pack/plugins/security/public/account_management/change_password/change_password.tsx
index 90d63d8b43bc7..ac0e284c8b9ad 100644
--- a/x-pack/plugins/security/public/account_management/change_password/change_password.tsx
+++ b/x-pack/plugins/security/public/account_management/change_password/change_password.tsx
@@ -17,13 +17,16 @@ import { canUserChangePassword } from '../../../common/model';
 import type { UserAPIClient } from '../../management/users';
 import { ChangePasswordForm } from '../../management/users/components/change_password_form';
 
-interface Props {
+export interface ChangePasswordProps {
   user: AuthenticatedUser;
+}
+
+export interface ChangePasswordPropsInternal extends ChangePasswordProps {
   userAPIClient: PublicMethodsOf<UserAPIClient>;
   notifications: NotificationsSetup;
 }
 
-export class ChangePassword extends Component<Props, {}> {
+export class ChangePassword extends Component<ChangePasswordPropsInternal, {}> {
   public render() {
     const canChangePassword = canUserChangePassword(this.props.user);
 
diff --git a/x-pack/plugins/security/public/account_management/change_password/change_password_async.tsx b/x-pack/plugins/security/public/account_management/change_password/change_password_async.tsx
new file mode 100644
index 0000000000000..a4ad769146e59
--- /dev/null
+++ b/x-pack/plugins/security/public/account_management/change_password/change_password_async.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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import type { CoreStart } from 'src/core/public';
+
+import { UserAPIClient } from '../../management/users';
+import type { ChangePasswordProps } from './change_password';
+
+export const getChangePasswordComponent = async (
+  core: CoreStart
+): Promise<React.FC<ChangePasswordProps>> => {
+  const { ChangePassword } = await import('./change_password');
+
+  return (props: ChangePasswordProps) => {
+    return (
+      <ChangePassword
+        notifications={core.notifications}
+        userAPIClient={new UserAPIClient(core.http)}
+        {...props}
+      />
+    );
+  };
+};
diff --git a/x-pack/plugins/security/public/account_management/change_password/index.ts b/x-pack/plugins/security/public/account_management/change_password/index.ts
index c73b497512cdf..028d0f6cc7497 100644
--- a/x-pack/plugins/security/public/account_management/change_password/index.ts
+++ b/x-pack/plugins/security/public/account_management/change_password/index.ts
@@ -6,3 +6,5 @@
  */
 
 export { ChangePassword } from './change_password';
+
+export type { ChangePasswordProps } from './change_password';
diff --git a/x-pack/plugins/security/public/account_management/index.ts b/x-pack/plugins/security/public/account_management/index.ts
index bfba213c632d0..2d1045723a6e1 100644
--- a/x-pack/plugins/security/public/account_management/index.ts
+++ b/x-pack/plugins/security/public/account_management/index.ts
@@ -6,3 +6,6 @@
  */
 
 export { accountManagementApp } from './account_management_app';
+
+export type { ChangePasswordProps } from './change_password';
+export type { PersonalInfoProps } from './personal_info';
diff --git a/x-pack/plugins/security/public/account_management/personal_info/index.ts b/x-pack/plugins/security/public/account_management/personal_info/index.ts
index a7d2873e85391..6dc6489afa8c5 100644
--- a/x-pack/plugins/security/public/account_management/personal_info/index.ts
+++ b/x-pack/plugins/security/public/account_management/personal_info/index.ts
@@ -6,3 +6,5 @@
  */
 
 export { PersonalInfo } from './personal_info';
+
+export type { PersonalInfoProps } from './personal_info';
diff --git a/x-pack/plugins/security/public/account_management/personal_info/personal_info.tsx b/x-pack/plugins/security/public/account_management/personal_info/personal_info.tsx
index e9de2b8a69bfa..20b21fc0c30ce 100644
--- a/x-pack/plugins/security/public/account_management/personal_info/personal_info.tsx
+++ b/x-pack/plugins/security/public/account_management/personal_info/personal_info.tsx
@@ -12,11 +12,11 @@ import { FormattedMessage } from '@kbn/i18n/react';
 
 import type { AuthenticatedUser } from '../../../common/model';
 
-interface Props {
+export interface PersonalInfoProps {
   user: AuthenticatedUser;
 }
 
-export const PersonalInfo = (props: Props) => {
+export const PersonalInfo = (props: PersonalInfoProps) => {
   return (
     <EuiDescribedFormGroup
       fullWidth
diff --git a/x-pack/plugins/security/public/account_management/personal_info/personal_info_async.tsx b/x-pack/plugins/security/public/account_management/personal_info/personal_info_async.tsx
new file mode 100644
index 0000000000000..5f57d41b5b0f8
--- /dev/null
+++ b/x-pack/plugins/security/public/account_management/personal_info/personal_info_async.tsx
@@ -0,0 +1,17 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import type { PersonalInfoProps } from './personal_info';
+
+export const getPersonalInfoComponent = async (): Promise<React.FC<PersonalInfoProps>> => {
+  const { PersonalInfo } = await import('./personal_info');
+  return (props: PersonalInfoProps) => {
+    return <PersonalInfo {...props} />;
+  };
+};
diff --git a/x-pack/plugins/security/public/mocks.ts b/x-pack/plugins/security/public/mocks.ts
index 829c3ced9dddb..b936f8d01cfd5 100644
--- a/x-pack/plugins/security/public/mocks.ts
+++ b/x-pack/plugins/security/public/mocks.ts
@@ -11,6 +11,7 @@ import { mockAuthenticatedUser } from '../common/model/authenticated_user.mock';
 import { authenticationMock } from './authentication/index.mock';
 import { navControlServiceMock } from './nav_control/index.mock';
 import { createSessionTimeoutMock } from './session/session_timeout.mock';
+import { getUiApiMock } from './ui_api/index.mock';
 
 function createSetupMock() {
   return {
@@ -23,6 +24,7 @@ function createStartMock() {
   return {
     authc: authenticationMock.createStart(),
     navControlService: navControlServiceMock.createStart(),
+    uiApi: getUiApiMock.createStart(),
   };
 }
 
diff --git a/x-pack/plugins/security/public/plugin.test.tsx b/x-pack/plugins/security/public/plugin.test.tsx
index 9c31919bd5d29..c4c551e4bb5b5 100644
--- a/x-pack/plugins/security/public/plugin.test.tsx
+++ b/x-pack/plugins/security/public/plugin.test.tsx
@@ -100,6 +100,12 @@ describe('Security Plugin', () => {
           features: {} as FeaturesPluginStart,
         })
       ).toEqual({
+        uiApi: {
+          components: {
+            getChangePassword: expect.any(Function),
+            getPersonalInfo: expect.any(Function),
+          },
+        },
         authc: {
           getCurrentUser: expect.any(Function),
           areAPIKeysEnabled: expect.any(Function),
diff --git a/x-pack/plugins/security/public/plugin.tsx b/x-pack/plugins/security/public/plugin.tsx
index 69533ea534802..fbb282ee246f9 100644
--- a/x-pack/plugins/security/public/plugin.tsx
+++ b/x-pack/plugins/security/public/plugin.tsx
@@ -30,6 +30,8 @@ import type { SecurityNavControlServiceStart } from './nav_control';
 import { SecurityNavControlService } from './nav_control';
 import { SecurityCheckupService } from './security_checkup';
 import { SessionExpired, SessionTimeout, UnauthorizedResponseHttpInterceptor } from './session';
+import type { UiApi } from './ui_api';
+import { getUiApi } from './ui_api';
 
 export interface PluginSetupDependencies {
   licensing: LicensingPluginSetup;
@@ -150,6 +152,7 @@ export class SecurityPlugin
     }
 
     return {
+      uiApi: getUiApi({ core }),
       navControlService: this.navControlService.start({ core }),
       authc: this.authc as AuthenticationServiceStart,
     };
@@ -184,4 +187,8 @@ export interface SecurityPluginStart {
    * Exposes authentication information about the currently logged in user.
    */
   authc: AuthenticationServiceStart;
+  /**
+   * Exposes UI components that will be loaded asynchronously.
+   */
+  uiApi: UiApi;
 }
diff --git a/x-pack/plugins/security/public/suspense_error_boundary/index.ts b/x-pack/plugins/security/public/suspense_error_boundary/index.ts
new file mode 100644
index 0000000000000..061923c8445c2
--- /dev/null
+++ b/x-pack/plugins/security/public/suspense_error_boundary/index.ts
@@ -0,0 +1,8 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export { SuspenseErrorBoundary } from './suspense_error_boundary';
diff --git a/x-pack/plugins/security/public/suspense_error_boundary/suspense_error_boundary.tsx b/x-pack/plugins/security/public/suspense_error_boundary/suspense_error_boundary.tsx
new file mode 100644
index 0000000000000..313401ff45bd9
--- /dev/null
+++ b/x-pack/plugins/security/public/suspense_error_boundary/suspense_error_boundary.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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { EuiLoadingSpinner } from '@elastic/eui';
+import type { PropsWithChildren } from 'react';
+import React, { Component, Suspense } from 'react';
+
+import { i18n } from '@kbn/i18n';
+import type { NotificationsStart } from 'src/core/public';
+
+interface Props {
+  notifications: NotificationsStart;
+}
+
+interface State {
+  error: Error | null;
+}
+
+export class SuspenseErrorBoundary extends Component<PropsWithChildren<Props>, State> {
+  state: State = {
+    error: null,
+  };
+
+  static getDerivedStateFromError(error: Error) {
+    // Update state so next render shows fallback UI.
+    return { error };
+  }
+
+  public componentDidCatch(error: Error) {
+    const { notifications } = this.props;
+    if (notifications) {
+      const title = i18n.translate('xpack.security.uiApi.errorBoundaryToastTitle', {
+        defaultMessage: 'Failed to load Kibana asset',
+      });
+      const toastMessage = i18n.translate('xpack.security.uiApi.errorBoundaryToastMessage', {
+        defaultMessage: 'Reload page to continue.',
+      });
+      notifications.toasts.addError(error, { title, toastMessage });
+    }
+  }
+
+  render() {
+    const { children, notifications } = this.props;
+    const { error } = this.state;
+    if (!notifications || error) {
+      return null;
+    }
+    return <Suspense fallback={<EuiLoadingSpinner />}>{children}</Suspense>;
+  }
+}
diff --git a/x-pack/plugins/security/public/ui_api/components.tsx b/x-pack/plugins/security/public/ui_api/components.tsx
new file mode 100644
index 0000000000000..a488bc359b538
--- /dev/null
+++ b/x-pack/plugins/security/public/ui_api/components.tsx
@@ -0,0 +1,43 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type { FC, PropsWithChildren, PropsWithRef } from 'react';
+import React from 'react';
+
+import type { CoreStart } from 'src/core/public';
+
+/**
+ * We're importing specific files here instead of passing them
+ * through the index file. It helps to keep the bundle size low.
+ *
+ * Importing async components through the index file increases the bundle size.
+ * It happens because the bundle starts to also include all the sync dependencies
+ * available through the index file.
+ */
+import { getChangePasswordComponent } from '../account_management/change_password/change_password_async';
+import { getPersonalInfoComponent } from '../account_management/personal_info/personal_info_async';
+import { LazyWrapper } from './lazy_wrapper';
+
+export interface GetComponentsOptions {
+  core: CoreStart;
+}
+
+export const getComponents = ({ core }: GetComponentsOptions) => {
+  /**
+   * Returns a function that creates a lazy-loading version of a component.
+   */
+  function wrapLazy<T>(fn: () => Promise<FC<T>>) {
+    return (props: JSX.IntrinsicAttributes & PropsWithRef<PropsWithChildren<T>>) => (
+      <LazyWrapper fn={fn} core={core} props={props} />
+    );
+  }
+
+  return {
+    getPersonalInfo: wrapLazy(getPersonalInfoComponent),
+    getChangePassword: wrapLazy(() => getChangePasswordComponent(core)),
+  };
+};
diff --git a/x-pack/plugins/security/public/ui_api/index.mock.ts b/x-pack/plugins/security/public/ui_api/index.mock.ts
new file mode 100644
index 0000000000000..c35f9342be6ca
--- /dev/null
+++ b/x-pack/plugins/security/public/ui_api/index.mock.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type { UiApi } from './';
+
+export const getUiApiMock = {
+  createStart: (): jest.Mocked<UiApi> => ({
+    components: {
+      getPersonalInfo: jest.fn(),
+      getChangePassword: jest.fn(),
+    },
+  }),
+};
diff --git a/x-pack/plugins/security/public/ui_api/index.ts b/x-pack/plugins/security/public/ui_api/index.ts
new file mode 100644
index 0000000000000..e53564074940a
--- /dev/null
+++ b/x-pack/plugins/security/public/ui_api/index.ts
@@ -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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type { ReactElement } from 'react';
+
+import type { CoreStart } from 'src/core/public';
+
+import type { ChangePasswordProps, PersonalInfoProps } from '../account_management';
+import { getComponents } from './components';
+
+interface GetUiApiOptions {
+  core: CoreStart;
+}
+
+type LazyComponentFn<T> = (props: T) => ReactElement;
+
+export interface UiApi {
+  components: {
+    getPersonalInfo: LazyComponentFn<PersonalInfoProps>;
+    getChangePassword: LazyComponentFn<ChangePasswordProps>;
+  };
+}
+
+export const getUiApi = ({ core }: GetUiApiOptions): UiApi => {
+  const components = getComponents({ core });
+
+  return {
+    components,
+  };
+};
diff --git a/x-pack/plugins/security/public/ui_api/lazy_wrapper.tsx b/x-pack/plugins/security/public/ui_api/lazy_wrapper.tsx
new file mode 100644
index 0000000000000..6a37b35df7327
--- /dev/null
+++ b/x-pack/plugins/security/public/ui_api/lazy_wrapper.tsx
@@ -0,0 +1,39 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type { FC, PropsWithChildren, PropsWithRef, ReactElement } from 'react';
+import React, { lazy, useMemo } from 'react';
+
+import type { CoreStart } from 'src/core/public';
+
+import { SuspenseErrorBoundary } from '../suspense_error_boundary';
+
+interface InternalProps<T> {
+  fn: () => Promise<FC<T>>;
+  core: CoreStart;
+  props: JSX.IntrinsicAttributes & PropsWithRef<PropsWithChildren<T>>;
+}
+
+export const LazyWrapper: <T>(props: InternalProps<T>) => ReactElement | null = ({
+  fn,
+  core,
+  props,
+}) => {
+  const { notifications } = core;
+
+  const LazyComponent = useMemo(() => lazy(() => fn().then((x) => ({ default: x }))), [fn]);
+
+  if (!notifications) {
+    return null;
+  }
+
+  return (
+    <SuspenseErrorBoundary notifications={notifications}>
+      <LazyComponent {...props} />
+    </SuspenseErrorBoundary>
+  );
+};
diff --git a/x-pack/plugins/security/server/authentication/authentication_service.mock.ts b/x-pack/plugins/security/server/authentication/authentication_service.mock.ts
index ba73d3b196d2f..9014e504b405b 100644
--- a/x-pack/plugins/security/server/authentication/authentication_service.mock.ts
+++ b/x-pack/plugins/security/server/authentication/authentication_service.mock.ts
@@ -8,10 +8,10 @@
 import type { DeeplyMockedKeys } from '@kbn/utility-types/jest';
 
 import { apiKeysMock } from './api_keys/api_keys.mock';
-import type { AuthenticationServiceStartInternal } from './authentication_service';
+import type { InternalAuthenticationServiceStart } from './authentication_service';
 
 export const authenticationServiceMock = {
-  createStart: (): DeeplyMockedKeys<AuthenticationServiceStartInternal> => ({
+  createStart: (): DeeplyMockedKeys<InternalAuthenticationServiceStart> => ({
     apiKeys: apiKeysMock.create(),
     login: jest.fn(),
     logout: jest.fn(),
diff --git a/x-pack/plugins/security/server/authentication/authentication_service.ts b/x-pack/plugins/security/server/authentication/authentication_service.ts
index 946fedbeee04f..79dcfb8d804b2 100644
--- a/x-pack/plugins/security/server/authentication/authentication_service.ts
+++ b/x-pack/plugins/security/server/authentication/authentication_service.ts
@@ -51,7 +51,7 @@ interface AuthenticationServiceStartParams {
   loggers: LoggerFactory;
 }
 
-export interface AuthenticationServiceStartInternal extends AuthenticationServiceStart {
+export interface InternalAuthenticationServiceStart extends AuthenticationServiceStart {
   apiKeys: Pick<
     APIKeys,
     | 'areAPIKeysEnabled'
@@ -227,7 +227,7 @@ export class AuthenticationService {
     legacyAuditLogger,
     loggers,
     session,
-  }: AuthenticationServiceStartParams): AuthenticationServiceStartInternal {
+  }: AuthenticationServiceStartParams): InternalAuthenticationServiceStart {
     const apiKeys = new APIKeys({
       clusterClient,
       logger: this.logger.get('api-key'),
diff --git a/x-pack/plugins/security/server/authentication/index.ts b/x-pack/plugins/security/server/authentication/index.ts
index 4f82c5653baa9..1e46d2aaf560e 100644
--- a/x-pack/plugins/security/server/authentication/index.ts
+++ b/x-pack/plugins/security/server/authentication/index.ts
@@ -9,7 +9,7 @@ export { canRedirectRequest } from './can_redirect_request';
 export {
   AuthenticationService,
   AuthenticationServiceStart,
-  AuthenticationServiceStartInternal,
+  InternalAuthenticationServiceStart,
 } from './authentication_service';
 export { AuthenticationResult } from './authentication_result';
 export { DeauthenticationResult } from './deauthentication_result';
diff --git a/x-pack/plugins/security/server/authorization/actions/actions.ts b/x-pack/plugins/security/server/authorization/actions/actions.ts
index d0466645213fa..0234c3bc82042 100644
--- a/x-pack/plugins/security/server/authorization/actions/actions.ts
+++ b/x-pack/plugins/security/server/authorization/actions/actions.ts
@@ -15,7 +15,7 @@ import { UIActions } from './ui';
 
 /** Actions are used to create the "actions" that are associated with Elasticsearch's
  * application privileges, and are used to perform the authorization checks implemented
- * by the various `checkPrivilegesWithRequest` derivatives
+ * by the various `checkPrivilegesWithRequest` derivatives.
  */
 export class Actions {
   public readonly api = new ApiActions(this.versionNumber);
diff --git a/x-pack/plugins/security/server/authorization/authorization_service.tsx b/x-pack/plugins/security/server/authorization/authorization_service.tsx
index c5adb3aff670e..0777c231ecd89 100644
--- a/x-pack/plugins/security/server/authorization/authorization_service.tsx
+++ b/x-pack/plugins/security/server/authorization/authorization_service.tsx
@@ -89,7 +89,7 @@ export interface AuthorizationServiceSetup {
   /**
    * Actions are used to create the "actions" that are associated with Elasticsearch's
    * application privileges, and are used to perform the authorization checks implemented
-   * by the various `checkPrivilegesWithRequest` derivatives
+   * by the various `checkPrivilegesWithRequest` derivatives.
    */
   actions: Actions;
   checkPrivilegesWithRequest: CheckPrivilegesWithRequest;
diff --git a/x-pack/plugins/security/server/plugin.ts b/x-pack/plugins/security/server/plugin.ts
index 98f1335b53450..d0403c0f170ea 100644
--- a/x-pack/plugins/security/server/plugin.ts
+++ b/x-pack/plugins/security/server/plugin.ts
@@ -37,12 +37,11 @@ import type { AuditServiceSetup } from './audit';
 import { AuditService, SecurityAuditLogger } from './audit';
 import type {
   AuthenticationServiceStart,
-  AuthenticationServiceStartInternal,
+  InternalAuthenticationServiceStart,
 } from './authentication';
 import { AuthenticationService } from './authentication';
-import type { AuthorizationServiceSetup } from './authorization';
+import type { AuthorizationServiceSetup, AuthorizationServiceSetupInternal } from './authorization';
 import { AuthorizationService } from './authorization';
-import type { AuthorizationServiceSetupInternal } from './authorization/authorization_service';
 import type { ConfigSchema, ConfigType } from './config';
 import { createConfig } from './config';
 import { ElasticsearchService } from './elasticsearch';
@@ -156,7 +155,7 @@ export class SecurityPlugin
   private readonly authenticationService = new AuthenticationService(
     this.initializerContext.logger.get('authentication')
   );
-  private authenticationStart?: AuthenticationServiceStartInternal;
+  private authenticationStart?: InternalAuthenticationServiceStart;
   private readonly getAuthentication = () => {
     if (!this.authenticationStart) {
       throw new Error(`authenticationStart is not registered!`);
diff --git a/x-pack/plugins/security/server/routes/api_keys/create.test.ts b/x-pack/plugins/security/server/routes/api_keys/create.test.ts
index ee28681adbd5f..a86481b8016e8 100644
--- a/x-pack/plugins/security/server/routes/api_keys/create.test.ts
+++ b/x-pack/plugins/security/server/routes/api_keys/create.test.ts
@@ -12,7 +12,7 @@ import type { RequestHandler } from 'src/core/server';
 import { kibanaResponseFactory } from 'src/core/server';
 import { httpServerMock } from 'src/core/server/mocks';
 
-import type { AuthenticationServiceStartInternal } from '../../authentication';
+import type { InternalAuthenticationServiceStart } from '../../authentication';
 import { authenticationServiceMock } from '../../authentication/authentication_service.mock';
 import type { SecurityRequestHandlerContext } from '../../types';
 import { routeDefinitionParamsMock } from '../index.mock';
@@ -28,7 +28,7 @@ describe('Create API Key route', () => {
   }
 
   let routeHandler: RequestHandler<any, any, any, any>;
-  let authc: DeeplyMockedKeys<AuthenticationServiceStartInternal>;
+  let authc: DeeplyMockedKeys<InternalAuthenticationServiceStart>;
   beforeEach(() => {
     authc = authenticationServiceMock.createStart();
     const mockRouteDefinitionParams = routeDefinitionParamsMock.create();
diff --git a/x-pack/plugins/security/server/routes/api_keys/enabled.test.ts b/x-pack/plugins/security/server/routes/api_keys/enabled.test.ts
index 1000e79563b57..6a477d2600d3e 100644
--- a/x-pack/plugins/security/server/routes/api_keys/enabled.test.ts
+++ b/x-pack/plugins/security/server/routes/api_keys/enabled.test.ts
@@ -12,7 +12,7 @@ import type { RequestHandler } from 'src/core/server';
 import { kibanaResponseFactory } from 'src/core/server';
 import { httpServerMock } from 'src/core/server/mocks';
 
-import type { AuthenticationServiceStartInternal } from '../../authentication';
+import type { InternalAuthenticationServiceStart } from '../../authentication';
 import { authenticationServiceMock } from '../../authentication/authentication_service.mock';
 import type { SecurityRequestHandlerContext } from '../../types';
 import { routeDefinitionParamsMock } from '../index.mock';
@@ -28,7 +28,7 @@ describe('API keys enabled', () => {
   }
 
   let routeHandler: RequestHandler<any, any, any, any>;
-  let authc: DeeplyMockedKeys<AuthenticationServiceStartInternal>;
+  let authc: DeeplyMockedKeys<InternalAuthenticationServiceStart>;
   beforeEach(() => {
     authc = authenticationServiceMock.createStart();
     const mockRouteDefinitionParams = routeDefinitionParamsMock.create();
diff --git a/x-pack/plugins/security/server/routes/authentication/common.test.ts b/x-pack/plugins/security/server/routes/authentication/common.test.ts
index 5acc5817bfb3e..8320f88d1242a 100644
--- a/x-pack/plugins/security/server/routes/authentication/common.test.ts
+++ b/x-pack/plugins/security/server/routes/authentication/common.test.ts
@@ -13,7 +13,7 @@ import { httpServerMock } from 'src/core/server/mocks';
 
 import type { SecurityLicense, SecurityLicenseFeatures } from '../../../common/licensing';
 import { mockAuthenticatedUser } from '../../../common/model/authenticated_user.mock';
-import type { AuthenticationServiceStartInternal } from '../../authentication';
+import type { InternalAuthenticationServiceStart } from '../../authentication';
 import {
   AuthenticationResult,
   DeauthenticationResult,
@@ -28,7 +28,7 @@ import { defineCommonRoutes } from './common';
 
 describe('Common authentication routes', () => {
   let router: jest.Mocked<SecurityRouter>;
-  let authc: DeeplyMockedKeys<AuthenticationServiceStartInternal>;
+  let authc: DeeplyMockedKeys<InternalAuthenticationServiceStart>;
   let license: jest.Mocked<SecurityLicense>;
   let mockContext: SecurityRequestHandlerContext;
   beforeEach(() => {
diff --git a/x-pack/plugins/security/server/routes/authentication/saml.test.ts b/x-pack/plugins/security/server/routes/authentication/saml.test.ts
index c28c435217ef3..d27ea5f6dca71 100644
--- a/x-pack/plugins/security/server/routes/authentication/saml.test.ts
+++ b/x-pack/plugins/security/server/routes/authentication/saml.test.ts
@@ -11,7 +11,7 @@ import type { RequestHandler, RouteConfig } from 'src/core/server';
 import { httpServerMock } from 'src/core/server/mocks';
 
 import { mockAuthenticatedUser } from '../../../common/model/authenticated_user.mock';
-import type { AuthenticationServiceStartInternal } from '../../authentication';
+import type { InternalAuthenticationServiceStart } from '../../authentication';
 import { AuthenticationResult, SAMLLogin } from '../../authentication';
 import { authenticationServiceMock } from '../../authentication/authentication_service.mock';
 import type { SecurityRouter } from '../../types';
@@ -21,7 +21,7 @@ import { defineSAMLRoutes } from './saml';
 
 describe('SAML authentication routes', () => {
   let router: jest.Mocked<SecurityRouter>;
-  let authc: DeeplyMockedKeys<AuthenticationServiceStartInternal>;
+  let authc: DeeplyMockedKeys<InternalAuthenticationServiceStart>;
   beforeEach(() => {
     const routeParamsMock = routeDefinitionParamsMock.create();
     router = routeParamsMock.router;
diff --git a/x-pack/plugins/security/server/routes/index.ts b/x-pack/plugins/security/server/routes/index.ts
index e36ca1b9ab72e..7a4310da3e4c7 100644
--- a/x-pack/plugins/security/server/routes/index.ts
+++ b/x-pack/plugins/security/server/routes/index.ts
@@ -10,7 +10,7 @@ import type { HttpResources, IBasePath, Logger } from 'src/core/server';
 
 import type { KibanaFeature } from '../../../features/server';
 import type { SecurityLicense } from '../../common/licensing';
-import type { AuthenticationServiceStartInternal } from '../authentication';
+import type { InternalAuthenticationServiceStart } from '../authentication';
 import type { AuthorizationServiceSetupInternal } from '../authorization';
 import type { ConfigType } from '../config';
 import type { SecurityFeatureUsageServiceStart } from '../feature_usage';
@@ -39,7 +39,7 @@ export interface RouteDefinitionParams {
   license: SecurityLicense;
   getFeatures: () => Promise<KibanaFeature[]>;
   getFeatureUsageService: () => SecurityFeatureUsageServiceStart;
-  getAuthenticationService: () => AuthenticationServiceStartInternal;
+  getAuthenticationService: () => InternalAuthenticationServiceStart;
 }
 
 export function defineRoutes(params: RouteDefinitionParams) {
diff --git a/x-pack/plugins/security/server/routes/users/change_password.test.ts b/x-pack/plugins/security/server/routes/users/change_password.test.ts
index e5f4381a20421..fba7bf4f872e7 100644
--- a/x-pack/plugins/security/server/routes/users/change_password.test.ts
+++ b/x-pack/plugins/security/server/routes/users/change_password.test.ts
@@ -16,7 +16,7 @@ import { coreMock, httpServerMock } from 'src/core/server/mocks';
 
 import { mockAuthenticatedUser } from '../../../common/model/authenticated_user.mock';
 import { AuthenticationResult } from '../../authentication';
-import type { AuthenticationServiceStartInternal } from '../../authentication/authentication_service';
+import type { InternalAuthenticationServiceStart } from '../../authentication';
 import { authenticationServiceMock } from '../../authentication/authentication_service.mock';
 import type { Session } from '../../session_management';
 import { sessionMock } from '../../session_management/session.mock';
@@ -26,7 +26,7 @@ import { defineChangeUserPasswordRoutes } from './change_password';
 
 describe('Change password', () => {
   let router: jest.Mocked<SecurityRouter>;
-  let authc: DeeplyMockedKeys<AuthenticationServiceStartInternal>;
+  let authc: DeeplyMockedKeys<InternalAuthenticationServiceStart>;
   let session: jest.Mocked<PublicMethodsOf<Session>>;
   let routeHandler: RequestHandler<any, any, any, SecurityRequestHandlerContext>;
   let routeConfig: RouteConfig<any, any, any, any>;
diff --git a/x-pack/plugins/security/server/saved_objects/index.ts b/x-pack/plugins/security/server/saved_objects/index.ts
index 837b3c594d396..364f639e9e9a3 100644
--- a/x-pack/plugins/security/server/saved_objects/index.ts
+++ b/x-pack/plugins/security/server/saved_objects/index.ts
@@ -9,7 +9,7 @@ import type { CoreSetup, LegacyRequest } from 'src/core/server';
 
 import { KibanaRequest, SavedObjectsClient } from '../../../../../src/core/server';
 import type { AuditServiceSetup, SecurityAuditLogger } from '../audit';
-import type { AuthorizationServiceSetupInternal } from '../authorization/authorization_service';
+import type { AuthorizationServiceSetupInternal } from '../authorization';
 import type { SpacesService } from '../plugin';
 import { SecureSavedObjectsClientWrapper } from './secure_saved_objects_client_wrapper';
 
diff --git a/x-pack/plugins/security_solution/common/endpoint/types/actions.ts b/x-pack/plugins/security_solution/common/endpoint/types/actions.ts
index 33072e8df5cec..937025f35dadc 100644
--- a/x-pack/plugins/security_solution/common/endpoint/types/actions.ts
+++ b/x-pack/plugins/security_solution/common/endpoint/types/actions.ts
@@ -6,7 +6,7 @@
  */
 
 import { TypeOf } from '@kbn/config-schema';
-import { HostIsolationRequestSchema } from '../schema/actions';
+import { ActionStatusRequestSchema, HostIsolationRequestSchema } from '../schema/actions';
 
 export type ISOLATION_ACTIONS = 'isolate' | 'unisolate';
 
@@ -44,10 +44,16 @@ export interface HostIsolationResponse {
   action: string;
 }
 
-export interface PendingActionsResponse {
+export interface EndpointPendingActions {
   agent_id: string;
   pending_actions: {
     /** Number of actions pending for each type. The `key` could be one of the `ISOLATION_ACTIONS` values. */
     [key: string]: number;
   };
 }
+
+export interface PendingActionsResponse {
+  data: EndpointPendingActions[];
+}
+
+export type PendingActionsRequestQuery = TypeOf<typeof ActionStatusRequestSchema.query>;
diff --git a/x-pack/plugins/security_solution/public/cases/components/callout/callout.test.tsx b/x-pack/plugins/security_solution/public/cases/components/callout/callout.test.tsx
index 926fe7b63fb5a..0a0caa40a8783 100644
--- a/x-pack/plugins/security_solution/public/cases/components/callout/callout.test.tsx
+++ b/x-pack/plugins/security_solution/public/cases/components/callout/callout.test.tsx
@@ -80,7 +80,7 @@ describe('Callout', () => {
   });
 
   it('dismiss the callout correctly', () => {
-    const wrapper = mount(<CallOut {...defaultProps} messages={[]} />);
+    const wrapper = mount(<CallOut {...defaultProps} />);
     expect(wrapper.find(`[data-test-subj="callout-dismiss-md5-hex"]`).exists()).toBeTruthy();
     wrapper.find(`button[data-test-subj="callout-dismiss-md5-hex"]`).simulate('click');
     wrapper.update();
diff --git a/x-pack/plugins/security_solution/public/cases/components/callout/callout.tsx b/x-pack/plugins/security_solution/public/cases/components/callout/callout.tsx
index 8e2f439f02c4b..4cd7fad10fe70 100644
--- a/x-pack/plugins/security_solution/public/cases/components/callout/callout.tsx
+++ b/x-pack/plugins/security_solution/public/cases/components/callout/callout.tsx
@@ -35,11 +35,9 @@ const CallOutComponent = ({
     type,
   ]);
 
-  return showCallOut ? (
+  return showCallOut && !isEmpty(messages) ? (
     <EuiCallOut title={title} color={type} iconType="gear" data-test-subj={`case-callout-${id}`}>
-      {!isEmpty(messages) && (
-        <EuiDescriptionList data-test-subj={`callout-messages-${id}`} listItems={messages} />
-      )}
+      <EuiDescriptionList data-test-subj={`callout-messages-${id}`} listItems={messages} />
       <EuiButton
         data-test-subj={`callout-dismiss-${id}`}
         color={type === 'success' ? 'secondary' : type}
diff --git a/x-pack/plugins/security_solution/public/cases/components/callout/helpers.tsx b/x-pack/plugins/security_solution/public/cases/components/callout/helpers.tsx
index 3409c5eb94245..29b17cd426c58 100644
--- a/x-pack/plugins/security_solution/public/cases/components/callout/helpers.tsx
+++ b/x-pack/plugins/security_solution/public/cases/components/callout/helpers.tsx
@@ -11,7 +11,7 @@ import md5 from 'md5';
 import * as i18n from './translations';
 import { ErrorMessage } from './types';
 
-export const savedObjectReadOnlyErrorMessage: ErrorMessage = {
+export const permissionsReadOnlyErrorMessage: ErrorMessage = {
   id: 'read-only-privileges-error',
   title: i18n.READ_ONLY_FEATURE_TITLE,
   description: <>{i18n.READ_ONLY_FEATURE_MSG}</>,
diff --git a/x-pack/plugins/security_solution/public/cases/pages/case.tsx b/x-pack/plugins/security_solution/public/cases/pages/case.tsx
index 4ec29b676afe6..9613e327ebe9f 100644
--- a/x-pack/plugins/security_solution/public/cases/pages/case.tsx
+++ b/x-pack/plugins/security_solution/public/cases/pages/case.tsx
@@ -12,7 +12,7 @@ import { useGetUserCasesPermissions } from '../../common/lib/kibana';
 import { SpyRoute } from '../../common/utils/route/spy_routes';
 import { AllCases } from '../components/all_cases';
 
-import { savedObjectReadOnlyErrorMessage, CaseCallOut } from '../components/callout';
+import { permissionsReadOnlyErrorMessage, CaseCallOut } from '../components/callout';
 import { CaseFeatureNoPermissions } from './feature_no_permissions';
 import { SecurityPageName } from '../../app/types';
 
@@ -24,8 +24,8 @@ export const CasesPage = React.memo(() => {
       <WrapperPage>
         {userPermissions != null && !userPermissions?.crud && userPermissions?.read && (
           <CaseCallOut
-            title={savedObjectReadOnlyErrorMessage.title}
-            messages={[{ ...savedObjectReadOnlyErrorMessage, title: '' }]}
+            title={permissionsReadOnlyErrorMessage.title}
+            messages={[{ ...permissionsReadOnlyErrorMessage, title: '' }]}
           />
         )}
         <AllCases userCanCrud={userPermissions?.crud ?? false} />
diff --git a/x-pack/plugins/security_solution/public/cases/pages/case_details.tsx b/x-pack/plugins/security_solution/public/cases/pages/case_details.tsx
index 03407c7a5adaa..bbc29828731cb 100644
--- a/x-pack/plugins/security_solution/public/cases/pages/case_details.tsx
+++ b/x-pack/plugins/security_solution/public/cases/pages/case_details.tsx
@@ -16,7 +16,7 @@ import { useGetUserCasesPermissions } from '../../common/lib/kibana';
 import { getCaseUrl } from '../../common/components/link_to';
 import { navTabs } from '../../app/home/home_navigations';
 import { CaseView } from '../components/case_view';
-import { savedObjectReadOnlyErrorMessage, CaseCallOut } from '../components/callout';
+import { permissionsReadOnlyErrorMessage, CaseCallOut } from '../components/callout';
 
 export const CaseDetailsPage = React.memo(() => {
   const history = useHistory();
@@ -37,8 +37,8 @@ export const CaseDetailsPage = React.memo(() => {
       <WrapperPage noPadding>
         {userPermissions != null && !userPermissions?.crud && userPermissions?.read && (
           <CaseCallOut
-            title={savedObjectReadOnlyErrorMessage.title}
-            messages={[{ ...savedObjectReadOnlyErrorMessage, title: '' }]}
+            title={permissionsReadOnlyErrorMessage.title}
+            messages={[{ ...permissionsReadOnlyErrorMessage, title: '' }]}
           />
         )}
         <CaseView
diff --git a/x-pack/plugins/security_solution/public/common/lib/host_isolation/index.test.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/index.test.ts
similarity index 100%
rename from x-pack/plugins/security_solution/public/common/lib/host_isolation/index.test.ts
rename to x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/index.test.ts
diff --git a/x-pack/plugins/security_solution/public/common/lib/host_isolation/index.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/index.ts
similarity index 100%
rename from x-pack/plugins/security_solution/public/common/lib/host_isolation/index.ts
rename to x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/index.ts
diff --git a/x-pack/plugins/security_solution/public/common/lib/host_isolation/mocks.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/mocks.ts
similarity index 100%
rename from x-pack/plugins/security_solution/public/common/lib/host_isolation/mocks.ts
rename to x-pack/plugins/security_solution/public/common/lib/endpoint_isolation/mocks.ts
diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/endpoint_pending_actions.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/endpoint_pending_actions.ts
new file mode 100644
index 0000000000000..e1feb8a14ab0b
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/endpoint_pending_actions.ts
@@ -0,0 +1,27 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import {
+  PendingActionsRequestQuery,
+  PendingActionsResponse,
+} from '../../../../common/endpoint/types';
+import { KibanaServices } from '../kibana';
+import { ACTION_STATUS_ROUTE } from '../../../../common/endpoint/constants';
+
+/**
+ * Retrieve a list of pending actions against the given Fleet Agent Ids provided on input
+ * @param agentIds
+ */
+export const fetchPendingActionsByAgentId = (
+  agentIds: PendingActionsRequestQuery['agent_ids']
+): Promise<PendingActionsResponse> => {
+  return KibanaServices.get().http.get<PendingActionsResponse>(ACTION_STATUS_ROUTE, {
+    query: {
+      agent_ids: agentIds,
+    },
+  });
+};
diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/index.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/index.ts
new file mode 100644
index 0000000000000..e3f7c7c3be90e
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/common/lib/endpoint_pending_actions/index.ts
@@ -0,0 +1,8 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export * from './endpoint_pending_actions';
diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts
index 4edbd5ab7e180..3baa6580b36fb 100644
--- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts
+++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts
@@ -25,7 +25,7 @@ import {
   UpdateAlertStatusProps,
   CasesFromAlertsResponse,
 } from './types';
-import { isolateHost, unIsolateHost } from '../../../../common/lib/host_isolation';
+import { isolateHost, unIsolateHost } from '../../../../common/lib/endpoint_isolation';
 import { resolvePathVariables } from '../../../../common/utils/resolve_path_variables';
 
 /**
diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts
index 6548d8a10ce97..98ef5a341ac9e 100644
--- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts
+++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts
@@ -41,7 +41,7 @@ import {
   hostIsolationHttpMocks,
   hostIsolationRequestBodyMock,
   hostIsolationResponseMock,
-} from '../../../../common/lib/host_isolation/mocks';
+} from '../../../../common/lib/endpoint_isolation/mocks';
 import { FleetActionGenerator } from '../../../../../common/endpoint/data_generators/fleet_action_generator';
 
 jest.mock('../../policy/store/services/ingest', () => ({
diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts
index 546116f82696b..a1da3c072293e 100644
--- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts
+++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts
@@ -53,7 +53,7 @@ import {
   createLoadedResourceState,
   createLoadingResourceState,
 } from '../../../state';
-import { isolateHost, unIsolateHost } from '../../../../common/lib/host_isolation';
+import { isolateHost, unIsolateHost } from '../../../../common/lib/endpoint_isolation';
 import { AppAction } from '../../../../common/store/actions';
 import { resolvePathVariables } from '../../../../common/utils/resolve_path_variables';
 import { ServerReturnedEndpointPackageInfo } from './action';
diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx
index 509bb7b4cf711..aa1c47a3102d9 100644
--- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx
@@ -29,7 +29,7 @@ import { POLICY_STATUS_TO_TEXT } from './host_constants';
 import { mockPolicyResultList } from '../../policy/store/test_mock_utils';
 import { getEndpointDetailsPath } from '../../../common/routing';
 import { KibanaServices, useKibana, useToasts } from '../../../../common/lib/kibana';
-import { hostIsolationHttpMocks } from '../../../../common/lib/host_isolation/mocks';
+import { hostIsolationHttpMocks } from '../../../../common/lib/endpoint_isolation/mocks';
 import { fireEvent } from '@testing-library/dom';
 import {
   isFailedResourceState,
diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/store/middleware.test.ts b/x-pack/plugins/security_solution/public/management/pages/event_filters/store/middleware.test.ts
index 5229e4078eb0d..530a18cd8a312 100644
--- a/x-pack/plugins/security_solution/public/management/pages/event_filters/store/middleware.test.ts
+++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/store/middleware.test.ts
@@ -22,6 +22,11 @@ import { EventFiltersListPageState, EventFiltersService } from '../types';
 import { getFoundExceptionListItemSchemaMock } from '../../../../../../lists/common/schemas/response/found_exception_list_item_schema.mock';
 import { isFailedResourceState, isLoadedResourceState } from '../../../state';
 import { getListFetchError } from './selector';
+import type {
+  ExceptionListItemSchema,
+  CreateExceptionListItemSchema,
+} from '@kbn/securitysolution-io-ts-list-types';
+import { Immutable } from '../../../../../common/endpoint/types';
 
 const createEventFiltersServiceMock = (): jest.Mocked<EventFiltersService> => ({
   addEventFilters: jest.fn(),
@@ -208,6 +213,38 @@ describe('Event filters middleware', () => {
       });
     });
 
+    it('does submit when entry has empty comments with white spaces', async () => {
+      service.addEventFilters.mockImplementation(
+        async (exception: Immutable<ExceptionListItemSchema | CreateExceptionListItemSchema>) => {
+          expect(exception.comments).toStrictEqual(createdEventFilterEntryMock().comments);
+          return createdEventFilterEntryMock();
+        }
+      );
+      const entry = getInitialExceptionFromEvent(ecsEventMock());
+      store.dispatch({
+        type: 'eventFiltersInitForm',
+        payload: { entry },
+      });
+
+      store.dispatch({
+        type: 'eventFiltersChangeForm',
+        payload: { newComment: '   ', entry },
+      });
+
+      store.dispatch({ type: 'eventFiltersCreateStart' });
+      await spyMiddleware.waitForAction('eventFiltersFormStateChanged');
+      expect(store.getState()).toStrictEqual({
+        ...initialState,
+        form: {
+          ...store.getState().form,
+          submissionResourceState: {
+            type: 'LoadedResourceState',
+            data: createdEventFilterEntryMock(),
+          },
+        },
+      });
+    });
+
     it('does throw error when creating', async () => {
       service.addEventFilters.mockRejectedValue({
         body: { message: 'error message', statusCode: 500, error: 'Internal Server Error' },
diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/store/middleware.ts b/x-pack/plugins/security_solution/public/management/pages/event_filters/store/middleware.ts
index a115ee9961de4..c1ade4e2cadec 100644
--- a/x-pack/plugins/security_solution/public/management/pages/event_filters/store/middleware.ts
+++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/store/middleware.ts
@@ -57,7 +57,8 @@ const addNewComments = (
 ): UpdateExceptionListItemSchema | CreateExceptionListItemSchema => {
   if (newComment) {
     if (!entry.comments) entry.comments = [];
-    entry.comments.push({ comment: newComment });
+    const trimmedComment = newComment.trim();
+    if (trimmedComment) entry.comments.push({ comment: trimmedComment });
   }
   return entry;
 };
diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/store/reducer.test.ts b/x-pack/plugins/security_solution/public/management/pages/event_filters/store/reducer.test.ts
index ed665135317af..5366b6dcf155a 100644
--- a/x-pack/plugins/security_solution/public/management/pages/event_filters/store/reducer.test.ts
+++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/store/reducer.test.ts
@@ -88,6 +88,25 @@ describe('event filters reducer', () => {
       });
     });
 
+    it('clean form after change form status', () => {
+      const entry = getInitialExceptionFromEvent(ecsEventMock());
+      const nameChanged = 'name changed';
+      const newComment = 'new comment';
+      const result = eventFiltersPageReducer(initialState, {
+        type: 'eventFiltersChangeForm',
+        payload: { entry: { ...entry, name: nameChanged }, newComment },
+      });
+      const cleanState = eventFiltersPageReducer(result, {
+        type: 'eventFiltersInitForm',
+        payload: { entry },
+      });
+
+      expect(cleanState).toStrictEqual({
+        ...initialState,
+        form: { ...initialState.form, entry, hasNameError: true, newComment: '' },
+      });
+    });
+
     it('create is success and force list refresh', () => {
       const initialStateWithListPageActive = {
         ...initialState,
diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/store/reducer.ts b/x-pack/plugins/security_solution/public/management/pages/event_filters/store/reducer.ts
index d69efb689c877..28292bdb1ed1c 100644
--- a/x-pack/plugins/security_solution/public/management/pages/event_filters/store/reducer.ts
+++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/store/reducer.ts
@@ -86,6 +86,7 @@ const eventFiltersInitForm: CaseReducer<EventFiltersInitForm> = (state, action)
       entry: action.payload.entry,
       hasNameError: !action.payload.entry.name,
       hasOSError: !action.payload.entry.os_types?.length,
+      newComment: '',
       submissionResourceState: {
         type: 'UninitialisedResourceState',
       },
diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/status.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/status.ts
index faaf41962a96c..66bb51b459c12 100644
--- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/status.ts
+++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/status.ts
@@ -10,7 +10,7 @@ import { TypeOf } from '@kbn/config-schema';
 import {
   EndpointAction,
   EndpointActionResponse,
-  PendingActionsResponse,
+  EndpointPendingActions,
 } from '../../../../common/endpoint/types';
 import { AGENT_ACTIONS_INDEX } from '../../../../../fleet/common';
 import { ActionStatusRequestSchema } from '../../../../common/endpoint/schema/actions';
@@ -99,7 +99,7 @@ export const actionStatusRequestHandler = function (
     const actionResponses = responseResults.body?.hits?.hits?.map((a) => a._source!) || [];
 
     // respond with action-count per agent
-    const response = agentIDs.map((aid) => {
+    const response: EndpointPendingActions[] = agentIDs.map((aid) => {
       const responseIDsFromAgent = actionResponses
         .filter((r) => r.agent_id === aid)
         .map((r) => r.action_id);
@@ -115,8 +115,8 @@ export const actionStatusRequestHandler = function (
               acc[cur] = 1;
             }
             return acc;
-          }, {} as PendingActionsResponse['pending_actions']),
-      } as PendingActionsResponse;
+          }, {} as EndpointPendingActions['pending_actions']),
+      };
     });
 
     return res.ok({
diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json
index 7c96dce3fac7f..8e52450d393b0 100644
--- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json
+++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json
@@ -2162,6 +2162,12 @@
                 "description": "Number of times the user opened one of the in-product help popovers."
               }
             },
+            "toggle_fullscreen_formula": {
+              "type": "long",
+              "_meta": {
+                "description": "Number of times the user toggled fullscreen mode on formula."
+              }
+            },
             "indexpattern_field_info_click": {
               "type": "long"
             },
@@ -2371,6 +2377,12 @@
               "_meta": {
                 "description": "Number of times the moving average function was selected"
               }
+            },
+            "indexpattern_dimension_operation_formula": {
+              "type": "long",
+              "_meta": {
+                "description": "Number of times the formula function was selected"
+              }
             }
           }
         },
@@ -2385,6 +2397,12 @@
                 "description": "Number of times the user opened one of the in-product help popovers."
               }
             },
+            "toggle_fullscreen_formula": {
+              "type": "long",
+              "_meta": {
+                "description": "Number of times the user toggled fullscreen mode on formula."
+              }
+            },
             "indexpattern_field_info_click": {
               "type": "long"
             },
@@ -2594,6 +2612,12 @@
               "_meta": {
                 "description": "Number of times the moving average function was selected"
               }
+            },
+            "indexpattern_dimension_operation_formula": {
+              "type": "long",
+              "_meta": {
+                "description": "Number of times the formula function was selected"
+              }
             }
           }
         },
@@ -2666,6 +2690,12 @@
             },
             "lnsMetric": {
               "type": "long"
+            },
+            "formula": {
+              "type": "long",
+              "_meta": {
+                "description": "Number of saved lens visualizations which are using at least one formula"
+              }
             }
           }
         },
@@ -2709,6 +2739,12 @@
             },
             "lnsMetric": {
               "type": "long"
+            },
+            "formula": {
+              "type": "long",
+              "_meta": {
+                "description": "Number of saved lens visualizations which are using at least one formula"
+              }
             }
           }
         },
@@ -2752,6 +2788,12 @@
             },
             "lnsMetric": {
               "type": "long"
+            },
+            "formula": {
+              "type": "long",
+              "_meta": {
+                "description": "Number of saved lens visualizations which are using at least one formula"
+              }
             }
           }
         }
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 8066ca178d34f..e47dfdf986eee 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -7966,7 +7966,7 @@
     "xpack.enterpriseSearch.roleMapping.filterRoleMappingsPlaceholder": "ロールをフィルタリング...",
     "xpack.enterpriseSearch.roleMapping.individualAuthProviderLabel": "個別の認証プロバイダーを選択",
     "xpack.enterpriseSearch.roleMapping.manageRoleMappingTitle": "ロールマッピングを管理",
-    "xpack.enterpriseSearch.roleMapping.moResults.message": "'{filterValue}'の結果が見つかりません。",
+    "xpack.enterpriseSearch.roleMapping.noResults.message": "の結果が見つかりません。",
     "xpack.enterpriseSearch.roleMapping.newRoleMappingTitle": "ロールマッピングを追加",
     "xpack.enterpriseSearch.roleMapping.roleLabel": "ロール",
     "xpack.enterpriseSearch.roleMapping.roleMappingsTitle": "ユーザーとロール",
@@ -8795,8 +8795,6 @@
     "xpack.fleet.agentDetailsIntegrations.viewLogsButton": "ログを表示",
     "xpack.fleet.agentEnrollment.agentDescription": "Elastic エージェントをホストに追加し、データを収集して、Elastic Stack に送信します。",
     "xpack.fleet.agentEnrollment.agentsNotInitializedText": "エージェントを登録する前に、{link}。",
-    "xpack.fleet.agentEnrollment.cancelButtonLabel": "キャンセル",
-    "xpack.fleet.agentEnrollment.continueButtonLabel": "続行",
     "xpack.fleet.agentEnrollment.copyPolicyButton": "クリップボードにコピー",
     "xpack.fleet.agentEnrollment.copyRunInstructionsButton": "クリップボードにコピー",
     "xpack.fleet.agentEnrollment.downloadDescription": "Elasticエージェントダウンロードページでは、エージェントバイナリと検証署名をダウンロードできます。",
@@ -14048,7 +14046,6 @@
     "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixLabel": "分類混同行列",
     "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixPredictedLabel": "予測されたクラス",
     "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixTestingHelpText": "データセットをテストするための正規化された混同行列",
-    "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixTooltip": "マルチクラス混同行列には、分析が実際のクラスで正しくデータポイントを分類した発生数と、別のクラスで誤分類した発生数が含まれます。",
     "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixTrainingHelpText": "データセットを学習するための正規化された混同行列",
     "xpack.ml.dataframe.analytics.classificationExploration.evaluateJobStatusLabel": "ジョブ状態",
     "xpack.ml.dataframe.analytics.classificationExploration.evaluateSectionAvgRecallTooltip": "平均再現率は、実際のクラスメンバーのデータポイントのうち正しくクラスメンバーとして特定された数を示します。",
@@ -17312,10 +17309,6 @@
     "xpack.observability.alertsTable.viewInAppButtonLabel": "アプリで表示",
     "xpack.observability.alertsTitle": "アラート",
     "xpack.observability.breadcrumbs.observability": "オブザーバビリティ",
-    "xpack.observability.cases.breadcrumb": "ケース",
-    "xpack.observability.casesDisclaimerText": "これは将来のケースのホームです。",
-    "xpack.observability.casesDisclaimerTitle": "まもなくリリース",
-    "xpack.observability.casesTitle": "ケース",
     "xpack.observability.emptySection.apps.alert.description": "503 エラーが累積していますか?サービスは応答していますか?CPUとRAMの使用量が跳ね上がっていますか?このような警告を、事後にではなく、発生と同時に把握しましょう。",
     "xpack.observability.emptySection.apps.alert.link": "アラートの作成",
     "xpack.observability.emptySection.apps.alert.title": "アラートが見つかりません。",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 33f5d4aceb51c..3ab6203b48942 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -8034,7 +8034,7 @@
     "xpack.enterpriseSearch.roleMapping.filterRoleMappingsPlaceholder": "筛选角色......",
     "xpack.enterpriseSearch.roleMapping.individualAuthProviderLabel": "选择单个身份验证提供程序",
     "xpack.enterpriseSearch.roleMapping.manageRoleMappingTitle": "管理角色映射",
-    "xpack.enterpriseSearch.roleMapping.moResults.message": "找不到“{filterValue}”的结果",
+    "xpack.enterpriseSearch.roleMapping.noResults.message": "找不到的结果",
     "xpack.enterpriseSearch.roleMapping.newRoleMappingTitle": "添加角色映射",
     "xpack.enterpriseSearch.roleMapping.roleLabel": "角色",
     "xpack.enterpriseSearch.roleMapping.roleMappingsTitle": "用户和角色",
@@ -8872,8 +8872,6 @@
     "xpack.fleet.agentDetailsIntegrations.viewLogsButton": "查看日志",
     "xpack.fleet.agentEnrollment.agentDescription": "将 Elastic 代理添加到您的主机,以收集数据并将其发送到 Elastic Stack。",
     "xpack.fleet.agentEnrollment.agentsNotInitializedText": "注册代理前,请{link}。",
-    "xpack.fleet.agentEnrollment.cancelButtonLabel": "取消",
-    "xpack.fleet.agentEnrollment.continueButtonLabel": "继续",
     "xpack.fleet.agentEnrollment.copyPolicyButton": "复制到剪贴板",
     "xpack.fleet.agentEnrollment.copyRunInstructionsButton": "复制到剪贴板",
     "xpack.fleet.agentEnrollment.downloadDescription": "可从 Elastic 代理下载页面下载代理二进制文件及其验证签名。",
@@ -14230,7 +14228,6 @@
     "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixLabel": "分类混淆矩阵",
     "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixPredictedLabel": "预测类",
     "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixTestingHelpText": "用于测试数据集的标准化混淆矩阵",
-    "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixTooltip": "多类混淆矩阵包含分析使用数据点的实际类正确分类数据点的次数以及分析使用其他类错误分类这些数据点的次数",
     "xpack.ml.dataframe.analytics.classificationExploration.confusionMatrixTrainingHelpText": "用于训练数据集的标准化混淆矩阵",
     "xpack.ml.dataframe.analytics.classificationExploration.evaluateJobStatusLabel": "作业状态",
     "xpack.ml.dataframe.analytics.classificationExploration.evaluateSectionAvgRecallTooltip": "平均召回率显示作为实际类成员的数据点有多少个已被正确标识为类成员。",
@@ -17549,10 +17546,6 @@
     "xpack.observability.alertsTable.viewInAppButtonLabel": "在应用中查看",
     "xpack.observability.alertsTitle": "告警",
     "xpack.observability.breadcrumbs.observability": "可观测性",
-    "xpack.observability.cases.breadcrumb": "案例",
-    "xpack.observability.casesDisclaimerText": "这是案例的未来之家。",
-    "xpack.observability.casesDisclaimerTitle": "即将推出",
-    "xpack.observability.casesTitle": "案例",
     "xpack.observability.emptySection.apps.alert.description": "503 错误是否越来越多?服务是否响应?CPU 和 RAM 利用率是否激增?实时查看警告,而不是事后再进行剖析。",
     "xpack.observability.emptySection.apps.alert.link": "创建告警",
     "xpack.observability.emptySection.apps.alert.title": "未找到告警。",
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 44c950a500040..b998067424edd 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
@@ -184,7 +184,7 @@ describe('health check', () => {
     const action = queryByText(/Learn/i);
     expect(action!.textContent).toMatchInlineSnapshot(`"Learn how.(opens in a new tab or window)"`);
     expect(action!.getAttribute('href')).toMatchInlineSnapshot(
-      `"https://www.elastic.co/guide/en/kibana/mocked-test-branch/alerting-getting-started.html#alerting-setup-prerequisites"`
+      `"https://www.elastic.co/guide/en/kibana/mocked-test-branch/alerting-setup.html#alerting-prerequisites"`
     );
   });
 });
diff --git a/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx
index 0e1c27c1e6768..3594374a54f16 100644
--- a/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx
+++ b/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx
@@ -37,7 +37,7 @@ describe('home', () => {
     const documentationLink = wrapper.find('[data-test-subj="documentationLink"]');
     expect(documentationLink.exists()).toBeTruthy();
     expect(documentationLink.first().prop('href')).toEqual(
-      'https://www.elastic.co/guide/en/kibana/mocked-test-branch/alert-management.html'
+      'https://www.elastic.co/guide/en/kibana/mocked-test-branch/create-and-manage-rules.html'
     );
   });
 });
diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana.test.ts
index 867440ae0d911..b14ec26e5c8af 100644
--- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana.test.ts
+++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana.test.ts
@@ -182,9 +182,7 @@ describe('Kibana deprecations', () => {
       component.update();
 
       expect(exists('kibanaRequestError')).toBe(true);
-      expect(find('kibanaRequestError').text()).toContain(
-        'Could not retrieve Kibana deprecations.'
-      );
+      expect(find('kibanaRequestError').text()).toContain('Could not retrieve Kibana deprecations');
     });
 
     test('handles deprecation service error', async () => {
@@ -217,7 +215,7 @@ describe('Kibana deprecations', () => {
       // Verify top-level callout renders
       expect(exists('kibanaPluginError')).toBe(true);
       expect(find('kibanaPluginError').text()).toContain(
-        'Not all Kibana deprecations were retrieved successfully.'
+        'Not all Kibana deprecations were retrieved successfully'
       );
 
       // Open all deprecations
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/coming_soon_prompt.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/coming_soon_prompt.tsx
index b7869226a84b0..14627f0b138b0 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/coming_soon_prompt.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/coming_soon_prompt.tsx
@@ -16,7 +16,7 @@ export const ComingSoonPrompt: React.FunctionComponent = () => {
   const { ELASTIC_WEBSITE_URL } = docLinks;
 
   return (
-    <EuiPageContent>
+    <EuiPageContent verticalPosition="center" horizontalPosition="center" color="subdued">
       <EuiEmptyPrompt
         iconType="wrench"
         data-test-subj="comingSoonPrompt"
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx
index 0da4a4877a7ec..4fc4d691c4038 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx
@@ -11,14 +11,12 @@ import { withRouter, RouteComponentProps } from 'react-router-dom';
 import {
   EuiButton,
   EuiButtonEmpty,
-  EuiPageBody,
   EuiPageHeader,
   EuiTabbedContent,
   EuiTabbedContentTab,
-  EuiPageContent,
-  EuiPageContentBody,
   EuiToolTip,
   EuiNotificationBadge,
+  EuiSpacer,
 } from '@elastic/eui';
 import { i18n } from '@kbn/i18n';
 
@@ -162,51 +160,49 @@ export const EsDeprecationsContent = withRouter(
     }, [api, tabName, isLoading]);
 
     return (
-      <EuiPageBody>
-        <EuiPageContent>
-          <EuiPageHeader
-            pageTitle={i18nTexts.pageTitle}
-            description={i18nTexts.pageDescription}
-            rightSideItems={[
-              <EuiButtonEmpty
-                href={docLinks.links.upgradeAssistant}
-                target="_blank"
-                iconType="help"
-                data-test-subj="documentationLink"
-              >
-                {i18nTexts.docLinkText}
-              </EuiButtonEmpty>,
-            ]}
-          >
-            <EuiToolTip position="bottom" content={i18nTexts.backupDataButton.tooltipText}>
-              <EuiButton
-                fill
-                href={getUrlForApp('management', {
-                  path: 'data/snapshot_restore',
-                })}
-                iconType="popout"
-                iconSide="right"
-                target="_blank"
-              >
-                {i18nTexts.backupDataButton.label}
-              </EuiButton>
-            </EuiToolTip>
-          </EuiPageHeader>
-
-          <EuiPageContentBody>
-            <EuiTabbedContent
-              data-test-subj={
-                telemetryState === TelemetryState.Running
-                  ? 'upgradeAssistantTelemetryRunning'
-                  : undefined
-              }
-              tabs={tabs}
-              onTabClick={onTabClick}
-              selectedTab={tabs.find((tab) => tab.id === tabName)}
-            />
-          </EuiPageContentBody>
-        </EuiPageContent>
-      </EuiPageBody>
+      <>
+        <EuiPageHeader
+          pageTitle={i18nTexts.pageTitle}
+          description={i18nTexts.pageDescription}
+          rightSideItems={[
+            <EuiButtonEmpty
+              href={docLinks.links.upgradeAssistant}
+              target="_blank"
+              iconType="help"
+              data-test-subj="documentationLink"
+            >
+              {i18nTexts.docLinkText}
+            </EuiButtonEmpty>,
+          ]}
+        >
+          <EuiToolTip position="bottom" content={i18nTexts.backupDataButton.tooltipText}>
+            <EuiButton
+              fill
+              href={getUrlForApp('management', {
+                path: 'data/snapshot_restore',
+              })}
+              iconType="popout"
+              iconSide="right"
+              target="_blank"
+            >
+              {i18nTexts.backupDataButton.label}
+            </EuiButton>
+          </EuiToolTip>
+        </EuiPageHeader>
+
+        <EuiSpacer size="l" />
+
+        <EuiTabbedContent
+          data-test-subj={
+            telemetryState === TelemetryState.Running
+              ? 'upgradeAssistantTelemetryRunning'
+              : undefined
+          }
+          tabs={tabs}
+          onTabClick={onTabClick}
+          selectedTab={tabs.find((tab) => tab.id === tabName)}
+        />
+      </>
     );
   }
 );
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx
index e6ba83919c31b..79ada21941b56 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx
@@ -7,44 +7,67 @@
 
 import React from 'react';
 import { i18n } from '@kbn/i18n';
-import { EuiCallOut } from '@elastic/eui';
+import { EuiPageContent, EuiEmptyPrompt } from '@elastic/eui';
 
 interface Props {
   errorType: 'pluginError' | 'requestError';
 }
 
 const i18nTexts = {
-  pluginError: i18n.translate('xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorMessage', {
-    defaultMessage:
-      'Not all Kibana deprecations were retrieved successfully. This list may be incomplete. Check the Kibana server logs for errors.',
-  }),
-  loadingError: i18n.translate(
-    'xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorMessage',
-    {
-      defaultMessage:
-        'Could not retrieve Kibana deprecations. Check the Kibana server logs for errors.',
-    }
-  ),
+  pluginError: {
+    title: i18n.translate('xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorTitle', {
+      defaultMessage: 'Not all Kibana deprecations were retrieved successfully',
+    }),
+    description: i18n.translate(
+      'xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorDescription',
+      {
+        defaultMessage: 'Check the Kibana server logs for errors.',
+      }
+    ),
+  },
+  loadingError: {
+    title: i18n.translate('xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorTitle', {
+      defaultMessage: 'Could not retrieve Kibana deprecations',
+    }),
+    description: i18n.translate(
+      'xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorDescription',
+      {
+        defaultMessage: 'Check the Kibana server logs for errors.',
+      }
+    ),
+  },
 };
 
 export const KibanaDeprecationErrors: React.FunctionComponent<Props> = ({ errorType }) => {
   if (errorType === 'pluginError') {
     return (
-      <EuiCallOut
-        title={i18nTexts.pluginError}
-        color="warning"
-        iconType="alert"
+      <EuiPageContent
+        verticalPosition="center"
+        horizontalPosition="center"
+        color="danger"
         data-test-subj="kibanaPluginError"
-      />
+      >
+        <EuiEmptyPrompt
+          iconType="alert"
+          title={<h2>{i18nTexts.pluginError.title}</h2>}
+          body={<p>{i18nTexts.pluginError.description}</p>}
+        />
+      </EuiPageContent>
     );
   }
 
   return (
-    <EuiCallOut
-      title={i18nTexts.loadingError}
+    <EuiPageContent
+      verticalPosition="center"
+      horizontalPosition="center"
       color="danger"
-      iconType="alert"
       data-test-subj="kibanaRequestError"
-    />
+    >
+      <EuiEmptyPrompt
+        iconType="alert"
+        title={<h2>{i18nTexts.loadingError.title}</h2>}
+        body={<p>{i18nTexts.loadingError.description}</p>}
+      />
+    </EuiPageContent>
   );
 };
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx
index a9608109728ba..31b5c80d5b377 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx
@@ -8,14 +8,7 @@
 import React, { useEffect, useState, useCallback } from 'react';
 import { withRouter, RouteComponentProps } from 'react-router-dom';
 
-import {
-  EuiButtonEmpty,
-  EuiPageBody,
-  EuiPageHeader,
-  EuiPageContent,
-  EuiPageContentBody,
-  EuiSpacer,
-} from '@elastic/eui';
+import { EuiButtonEmpty, EuiPageContent, EuiPageHeader, EuiSpacer } from '@elastic/eui';
 import { i18n } from '@kbn/i18n';
 
 import type { DomainDeprecationDetails } from 'kibana/public';
@@ -135,46 +128,28 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent
     getAllDeprecations();
   }, [deprecations, getAllDeprecations]);
 
-  const getPageContent = () => {
-    if (kibanaDeprecations && kibanaDeprecations.length === 0) {
-      return (
+  if (kibanaDeprecations && kibanaDeprecations.length === 0) {
+    return (
+      <EuiPageContent verticalPosition="center" horizontalPosition="center" color="subdued">
         <NoDeprecationsPrompt
           deprecationType={i18nTexts.deprecationLabel}
           navigateToOverviewPage={() => history.push('/overview')}
         />
-      );
-    }
-
-    let content: React.ReactNode;
-
-    if (isLoading) {
-      content = <SectionLoading>{i18nTexts.isLoading}</SectionLoading>;
-    } else if (kibanaDeprecations?.length) {
-      content = (
-        <KibanaDeprecationList
-          deprecations={kibanaDeprecations}
-          showStepsModal={toggleStepsModal}
-          showResolveModal={toggleResolveModal}
-          reloadDeprecations={getAllDeprecations}
-          isLoading={isLoading}
-        />
-      );
-    } else if (error) {
-      content = <KibanaDeprecationErrors errorType="requestError" />;
-    }
+      </EuiPageContent>
+    );
+  }
 
+  if (isLoading) {
     return (
-      <div data-test-subj="kibanaDeprecationsContent">
-        <EuiSpacer />
-        {content}
-      </div>
+      <EuiPageContent verticalPosition="center" horizontalPosition="center" color="subdued">
+        <SectionLoading>{i18nTexts.isLoading}</SectionLoading>
+      </EuiPageContent>
     );
-  };
-
-  return (
-    <EuiPageBody>
-      <EuiPageContent>
+  } else if (kibanaDeprecations?.length) {
+    return (
+      <div data-test-subj="kibanaDeprecationsContent">
         <EuiPageHeader
+          bottomBorder
           pageTitle={i18nTexts.pageTitle}
           description={i18nTexts.pageDescription}
           rightSideItems={[
@@ -189,23 +164,33 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent
           ]}
         />
 
-        <EuiPageContentBody>
-          {getPageContent()}
-
-          {stepsModalContent && (
-            <StepsModal closeModal={() => toggleStepsModal()} modalContent={stepsModalContent} />
-          )}
-
-          {resolveModalContent && (
-            <ResolveDeprecationModal
-              closeModal={() => toggleResolveModal()}
-              resolveDeprecation={resolveDeprecation}
-              isResolvingDeprecation={isResolvingDeprecation}
-              deprecation={resolveModalContent}
-            />
-          )}
-        </EuiPageContentBody>
-      </EuiPageContent>
-    </EuiPageBody>
-  );
+        <EuiSpacer size="l" />
+
+        <KibanaDeprecationList
+          deprecations={kibanaDeprecations}
+          showStepsModal={toggleStepsModal}
+          showResolveModal={toggleResolveModal}
+          reloadDeprecations={getAllDeprecations}
+          isLoading={isLoading}
+        />
+
+        {stepsModalContent && (
+          <StepsModal closeModal={() => toggleStepsModal()} modalContent={stepsModalContent} />
+        )}
+
+        {resolveModalContent && (
+          <ResolveDeprecationModal
+            closeModal={() => toggleResolveModal()}
+            resolveDeprecation={resolveDeprecation}
+            isResolvingDeprecation={isResolvingDeprecation}
+            deprecation={resolveModalContent}
+          />
+        )}
+      </div>
+    );
+  } else if (error) {
+    return <KibanaDeprecationErrors errorType="requestError" />;
+  }
+
+  return null;
 });
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx
index 6b3048b669aa2..b77d4a337295c 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx
@@ -8,11 +8,9 @@
 import React, { FunctionComponent, useEffect } from 'react';
 
 import {
-  EuiPageContent,
   EuiPageContentBody,
   EuiText,
   EuiPageHeader,
-  EuiPageBody,
   EuiButtonEmpty,
   EuiFlexItem,
   EuiFlexGroup,
@@ -91,72 +89,68 @@ export const DeprecationsOverview: FunctionComponent<Props> = ({ history }) => {
   }, [breadcrumbs]);
 
   return (
-    <EuiPageBody>
-      <EuiPageContent data-test-subj="overviewPageContent">
-        <EuiPageHeader
-          pageTitle={i18nTexts.pageTitle}
-          rightSideItems={[
-            <EuiButtonEmpty
-              href={docLinks.links.upgradeAssistant}
-              target="_blank"
-              iconType="help"
-              data-test-subj="documentationLink"
-            >
-              {i18nTexts.docLink}
-            </EuiButtonEmpty>,
-          ]}
-        />
-
-        <EuiPageContentBody>
-          <>
-            <EuiText data-test-subj="overviewDetail" grow={false}>
-              <p>{i18nTexts.pageDescription}</p>
-            </EuiText>
-
-            <EuiSpacer />
-
-            {/* Remove this in last minor of the current major (e.g., 7.15) */}
-            <LatestMinorBanner />
-
-            <EuiSpacer size="xl" />
-
-            {/* Deprecation stats */}
-            <EuiFlexGroup>
-              <EuiFlexItem>
-                <ESDeprecationStats history={history} />
-              </EuiFlexItem>
-
-              <EuiFlexItem>
-                <KibanaDeprecationStats history={history} />
-              </EuiFlexItem>
-            </EuiFlexGroup>
-
-            <EuiSpacer />
-
-            {/* Deprecation logging */}
-            <EuiFlexGroup>
-              <EuiFlexItem>
-                <EuiTitle size="s">
-                  <h2>{i18nTexts.deprecationLoggingTitle}</h2>
-                </EuiTitle>
-
-                <EuiText>
-                  <p>
-                    {i18nTexts.getDeprecationLoggingDescription(
-                      `${nextMajor}.x`,
-                      docLinks.links.elasticsearch.deprecationLogging
-                    )}
-                  </p>
-                </EuiText>
-
-                <EuiSpacer size="m" />
-
-                <DeprecationLoggingToggle />
-              </EuiFlexItem>
-            </EuiFlexGroup>
-          </>
-        </EuiPageContentBody>
-      </EuiPageContent>
-    </EuiPageBody>
+    <div data-test-subj="overviewPageContent">
+      <EuiPageHeader
+        bottomBorder
+        pageTitle={i18nTexts.pageTitle}
+        description={i18nTexts.pageDescription}
+        rightSideItems={[
+          <EuiButtonEmpty
+            href={docLinks.links.upgradeAssistant}
+            target="_blank"
+            iconType="help"
+            data-test-subj="documentationLink"
+          >
+            {i18nTexts.docLink}
+          </EuiButtonEmpty>,
+        ]}
+      />
+
+      <EuiSpacer size="l" />
+
+      <EuiPageContentBody>
+        <>
+          {/* Remove this in last minor of the current major (e.g., 7.15) */}
+          <LatestMinorBanner />
+
+          <EuiSpacer size="xl" />
+
+          {/* Deprecation stats */}
+          <EuiFlexGroup>
+            <EuiFlexItem>
+              <ESDeprecationStats history={history} />
+            </EuiFlexItem>
+
+            <EuiFlexItem>
+              <KibanaDeprecationStats history={history} />
+            </EuiFlexItem>
+          </EuiFlexGroup>
+
+          <EuiSpacer />
+
+          {/* Deprecation logging */}
+          <EuiFlexGroup>
+            <EuiFlexItem>
+              <EuiTitle size="s">
+                <h2>{i18nTexts.deprecationLoggingTitle}</h2>
+              </EuiTitle>
+
+              <EuiText>
+                <p>
+                  {i18nTexts.getDeprecationLoggingDescription(
+                    `${nextMajor}.x`,
+                    docLinks.links.elasticsearch.deprecationLogging
+                  )}
+                </p>
+              </EuiText>
+
+              <EuiSpacer size="m" />
+
+              <DeprecationLoggingToggle />
+            </EuiFlexItem>
+          </EuiFlexGroup>
+        </>
+      </EuiPageContentBody>
+    </div>
   );
 };
diff --git a/x-pack/plugins/uptime/public/components/overview/alerts/alert_query_bar/query_bar.tsx b/x-pack/plugins/uptime/public/components/overview/alerts/alert_query_bar/query_bar.tsx
index 6293dc2ec1d18..0a0bbadb6216f 100644
--- a/x-pack/plugins/uptime/public/components/overview/alerts/alert_query_bar/query_bar.tsx
+++ b/x-pack/plugins/uptime/public/components/overview/alerts/alert_query_bar/query_bar.tsx
@@ -46,7 +46,7 @@ export const AlertQueryBar = ({ query = '', onChange }: Props) => {
         }}
         query={{ query: inputVal, language: 'kuery' }}
         aria-label={labels.ALERT_KUERY_BAR_ARIA}
-        data-test-subj="xpack.uptime.alerts.monitorStatus.filterBar"
+        dataTestSubj="xpack.uptime.alerts.monitorStatus.filterBar"
         autoSubmit={true}
         disableLanguageSwitcher={true}
         isInvalid={!!(inputVal && !query)}
diff --git a/x-pack/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_monitor_status.tsx b/x-pack/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_monitor_status.tsx
index d55f3fb336a9d..ff2ef4d2359a8 100644
--- a/x-pack/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_monitor_status.tsx
+++ b/x-pack/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_monitor_status.tsx
@@ -38,16 +38,19 @@ export const AlertMonitorStatus: React.FC<Props> = ({
 }) => {
   const dispatch = useDispatch();
   useEffect(() => {
-    dispatch(
-      fetchOverviewFilters({
-        dateRangeStart: 'now-24h',
-        dateRangeEnd: 'now',
-        locations: alertParams.filters?.['observer.geo.name'] ?? [],
-        ports: alertParams.filters?.['url.port'] ?? [],
-        tags: alertParams.filters?.tags ?? [],
-        schemes: alertParams.filters?.['monitor.type'] ?? [],
-      })
-    );
+    if (!window.location.pathname.includes('/app/uptime')) {
+      // filters inside uptime app already loaded
+      dispatch(
+        fetchOverviewFilters({
+          dateRangeStart: 'now-24h',
+          dateRangeEnd: 'now',
+          locations: alertParams.filters?.['observer.geo.name'] ?? [],
+          ports: alertParams.filters?.['url.port'] ?? [],
+          tags: alertParams.filters?.tags ?? [],
+          schemes: alertParams.filters?.['monitor.type'] ?? [],
+        })
+      );
+    }
   }, [alertParams, dispatch]);
 
   const overviewFilters = useSelector(overviewFiltersSelector);
diff --git a/x-pack/plugins/uptime/server/index.ts b/x-pack/plugins/uptime/server/index.ts
index c5427997b60a8..4894c73c625c1 100644
--- a/x-pack/plugins/uptime/server/index.ts
+++ b/x-pack/plugins/uptime/server/index.ts
@@ -8,6 +8,5 @@
 import { PluginInitializerContext } from '../../../../src/core/server';
 import { Plugin } from './plugin';
 
-export { initServerWithKibana, KibanaServer } from './kibana.index';
 export const plugin = (initializerContext: PluginInitializerContext) =>
   new Plugin(initializerContext);
diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts
index 4aa6ed830059e..e9ed14fbcddcd 100644
--- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts
+++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts
@@ -217,6 +217,7 @@ instanceStateValue: true
                 ruleTypeId: 'test.always-firing',
                 outcome: 'success',
                 message: `alert executed: test.always-firing:${alertId}: 'abc'`,
+                ruleObject: alertSearchResultWithoutDates,
               });
               break;
             default:
@@ -1249,10 +1250,11 @@ instanceStateValue: true
     outcome: string;
     message: string;
     errorMessage?: string;
+    ruleObject: any;
   }
 
   async function validateEventLog(params: ValidateEventLogParams): Promise<void> {
-    const { spaceId, alertId, ruleTypeId, outcome, message, errorMessage } = params;
+    const { spaceId, alertId, outcome, message, errorMessage, ruleObject } = params;
 
     const events: IValidatedEvent[] = await retry.try(async () => {
       return await getEventLog({
@@ -1293,10 +1295,19 @@ instanceStateValue: true
         type: 'alert',
         id: alertId,
         namespace: spaceId,
-        type_id: ruleTypeId,
+        type_id: ruleObject.alertInfo.ruleTypeId,
       },
     ]);
 
+    expect(event?.rule).to.eql({
+      id: alertId,
+      license: 'basic',
+      category: ruleObject.alertInfo.ruleTypeId,
+      ruleset: ruleObject.alertInfo.producer,
+      namespace: spaceId,
+      name: ruleObject.alertInfo.name,
+    });
+
     expect(event?.message).to.eql(message);
 
     if (errorMessage) {
diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/event_log.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/event_log.ts
index d5e55a66ecf08..5d13d641367a4 100644
--- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/event_log.ts
+++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/event_log.ts
@@ -81,6 +81,13 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
         errorMessage: 'Unable to decrypt attribute "apiKey"',
         status: 'error',
         reason: 'decrypt',
+        rule: {
+          id: alertId,
+          category: response.body.rule_type_id,
+          license: 'basic',
+          ruleset: 'alertsFixture',
+          namespace: spaceId,
+        },
       });
     });
   });
diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/event_log.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/event_log.ts
index c1f6bcb9e1510..781967ff5596a 100644
--- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/event_log.ts
+++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/event_log.ts
@@ -134,6 +134,14 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
               outcome: 'success',
               message: `alert executed: test.patternFiring:${alertId}: 'abc'`,
               status: executeStatuses[executeCount++],
+              rule: {
+                id: alertId,
+                category: response.body.rule_type_id,
+                license: 'basic',
+                ruleset: 'alertsFixture',
+                namespace: Spaces.space1.id,
+                name: response.body.name,
+              },
             });
             break;
           case 'execute-action':
@@ -146,6 +154,14 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
               message: `alert: test.patternFiring:${alertId}: 'abc' instanceId: 'instance' scheduled actionGroup: 'default' action: test.noop:${createdAction.id}`,
               instanceId: 'instance',
               actionGroupId: 'default',
+              rule: {
+                id: alertId,
+                category: response.body.rule_type_id,
+                license: 'basic',
+                ruleset: 'alertsFixture',
+                namespace: Spaces.space1.id,
+                name: response.body.name,
+              },
             });
             break;
           case 'new-instance':
@@ -181,6 +197,14 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
           instanceId: 'instance',
           actionGroupId: 'default',
           shouldHaveEventEnd,
+          rule: {
+            id: alertId,
+            category: response.body.rule_type_id,
+            license: 'basic',
+            ruleset: 'alertsFixture',
+            namespace: Spaces.space1.id,
+            name: response.body.name,
+          },
         });
       }
     });
@@ -279,6 +303,14 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
               outcome: 'success',
               message: `alert executed: test.patternFiring:${alertId}: 'abc'`,
               status: executeStatuses[executeCount++],
+              rule: {
+                id: alertId,
+                category: response.body.rule_type_id,
+                license: 'basic',
+                ruleset: 'alertsFixture',
+                namespace: Spaces.space1.id,
+                name: response.body.name,
+              },
             });
             break;
           case 'execute-action':
@@ -294,6 +326,14 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
               message: `alert: test.patternFiring:${alertId}: 'abc' instanceId: 'instance' scheduled actionGroup(subgroup): 'default(${event?.kibana?.alerting?.action_subgroup})' action: test.noop:${createdAction.id}`,
               instanceId: 'instance',
               actionGroupId: 'default',
+              rule: {
+                id: alertId,
+                category: response.body.rule_type_id,
+                license: 'basic',
+                ruleset: 'alertsFixture',
+                namespace: Spaces.space1.id,
+                name: response.body.name,
+              },
             });
             break;
           case 'new-instance':
@@ -332,6 +372,14 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
           instanceId: 'instance',
           actionGroupId: 'default',
           shouldHaveEventEnd,
+          rule: {
+            id: alertId,
+            category: response.body.rule_type_id,
+            license: 'basic',
+            ruleset: 'alertsFixture',
+            namespace: Spaces.space1.id,
+            name: response.body.name,
+          },
         });
       }
     });
@@ -374,6 +422,13 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
         errorMessage: 'this alert is intended to fail',
         status: 'error',
         reason: 'execute',
+        rule: {
+          id: alertId,
+          category: response.body.rule_type_id,
+          license: 'basic',
+          ruleset: 'alertsFixture',
+          namespace: Spaces.space1.id,
+        },
       });
     });
   });
@@ -397,10 +452,21 @@ interface ValidateEventLogParams {
   actionGroupId?: string;
   instanceId?: string;
   reason?: string;
+  rule: {
+    id: string;
+    name?: string;
+    version?: string;
+    category?: string;
+    reference?: string;
+    author?: string[];
+    license?: string;
+    ruleset?: string;
+    namespace?: string;
+  };
 }
 
 export function validateEvent(event: IValidatedEvent, params: ValidateEventLogParams): void {
-  const { spaceId, savedObjects, outcome, message, errorMessage } = params;
+  const { spaceId, savedObjects, outcome, message, errorMessage, rule } = params;
   const { status, actionGroupId, instanceId, reason, shouldHaveEventEnd } = params;
 
   if (status) {
@@ -456,6 +522,8 @@ export function validateEvent(event: IValidatedEvent, params: ValidateEventLogPa
 
   expect(event?.message).to.eql(message);
 
+  expect(event?.rule).to.eql(rule);
+
   if (errorMessage) {
     expect(event?.error?.message).to.eql(errorMessage);
   }
diff --git a/x-pack/test/api_integration/apis/features/features/features.ts b/x-pack/test/api_integration/apis/features/features/features.ts
index 25f38222bfb6c..275626664bef0 100644
--- a/x-pack/test/api_integration/apis/features/features/features.ts
+++ b/x-pack/test/api_integration/apis/features/features/features.ts
@@ -114,6 +114,7 @@ export default function ({ getService }: FtrProviderContext) {
             'infrastructure',
             'logs',
             'maps',
+            'observabilityCases',
             'uptime',
             'siem',
             'fleet',
diff --git a/x-pack/test/api_integration/apis/security/privileges.ts b/x-pack/test/api_integration/apis/security/privileges.ts
index 45b19ae3fe6fe..2468bfec63321 100644
--- a/x-pack/test/api_integration/apis/security/privileges.ts
+++ b/x-pack/test/api_integration/apis/security/privileges.ts
@@ -60,6 +60,7 @@ export default function ({ getService }: FtrProviderContext) {
             canvas: ['all', 'read', 'minimal_all', 'minimal_read', 'generate_report'],
             infrastructure: ['all', 'read'],
             logs: ['all', 'read'],
+            observabilityCases: ['all', 'read'],
             uptime: ['all', 'read'],
             apm: ['all', 'read'],
             ml: ['all', 'read'],
diff --git a/x-pack/test/api_integration/apis/security/privileges_basic.ts b/x-pack/test/api_integration/apis/security/privileges_basic.ts
index 0893bb49cd215..25266da2cdfb3 100644
--- a/x-pack/test/api_integration/apis/security/privileges_basic.ts
+++ b/x-pack/test/api_integration/apis/security/privileges_basic.ts
@@ -33,6 +33,7 @@ export default function ({ getService }: FtrProviderContext) {
             maps: ['all', 'read'],
             canvas: ['all', 'read'],
             infrastructure: ['all', 'read'],
+            observabilityCases: ['all', 'read'],
             logs: ['all', 'read'],
             uptime: ['all', 'read'],
             apm: ['all', 'read'],
diff --git a/x-pack/test/functional/apps/lens/formula.ts b/x-pack/test/functional/apps/lens/formula.ts
new file mode 100644
index 0000000000000..e9e5051c006f0
--- /dev/null
+++ b/x-pack/test/functional/apps/lens/formula.ts
@@ -0,0 +1,198 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import expect from '@kbn/expect';
+import { FtrProviderContext } from '../../ftr_provider_context';
+
+export default function ({ getService, getPageObjects }: FtrProviderContext) {
+  const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header']);
+  const find = getService('find');
+  const listingTable = getService('listingTable');
+  const browser = getService('browser');
+  const testSubjects = getService('testSubjects');
+
+  describe('lens formula', () => {
+    it('should transition from count to formula', async () => {
+      await PageObjects.visualize.gotoVisualizationLandingPage();
+      await listingTable.searchForItemWithName('lnsXYvis');
+      await PageObjects.lens.clickVisualizeListItemTitle('lnsXYvis');
+      await PageObjects.lens.goToTimeRange();
+
+      await PageObjects.lens.configureDimension({
+        dimension: 'lnsXY_yDimensionPanel > lns-dimensionTrigger',
+        operation: 'average',
+        field: 'bytes',
+        keepOpen: true,
+      });
+
+      await PageObjects.lens.switchToFormula();
+      await PageObjects.header.waitUntilLoadingHasFinished();
+      // .echLegendItem__title is the only viable way of getting the xy chart's
+      // legend item(s), so we're using a class selector here.
+      // 4th item is the other bucket
+      expect(await find.allByCssSelector('.echLegendItem')).to.have.length(3);
+    });
+
+    it('should update and delete a formula', async () => {
+      await PageObjects.visualize.navigateToNewVisualization();
+      await PageObjects.visualize.clickVisType('lens');
+      await PageObjects.lens.goToTimeRange();
+      await PageObjects.lens.switchToVisualization('lnsDatatable');
+
+      await PageObjects.lens.configureDimension({
+        dimension: 'lnsDatatable_metrics > lns-empty-dimension',
+        operation: 'formula',
+        formula: `count(kql=`,
+        keepOpen: true,
+      });
+
+      const input = await find.activeElement();
+      await input.type('*');
+
+      await PageObjects.header.waitUntilLoadingHasFinished();
+      expect(await PageObjects.lens.getDatatableCellText(0, 0)).to.eql('14,005');
+    });
+
+    it('should insert single quotes and escape when needed to create valid KQL', async () => {
+      await PageObjects.visualize.navigateToNewVisualization();
+      await PageObjects.visualize.clickVisType('lens');
+      await PageObjects.lens.goToTimeRange();
+      await PageObjects.lens.switchToVisualization('lnsDatatable');
+
+      await PageObjects.lens.configureDimension({
+        dimension: 'lnsDatatable_metrics > lns-empty-dimension',
+        operation: 'formula',
+        formula: `count(kql=`,
+        keepOpen: true,
+      });
+
+      let input = await find.activeElement();
+      await input.type(' ');
+      await input.pressKeys(browser.keys.ARROW_LEFT);
+      await input.type(`Men's Clothing`);
+
+      await PageObjects.common.sleep(100);
+
+      let element = await find.byCssSelector('.monaco-editor');
+      expect(await element.getVisibleText()).to.equal(`count(kql='Men\\'s Clothing ')`);
+
+      await PageObjects.lens.typeFormula('count(kql=');
+      input = await find.activeElement();
+      await input.type(`Men\'s Clothing`);
+
+      element = await find.byCssSelector('.monaco-editor');
+      expect(await element.getVisibleText()).to.equal(`count(kql='Men\\'s Clothing')`);
+    });
+
+    it('should persist a broken formula on close', async () => {
+      await PageObjects.visualize.navigateToNewVisualization();
+      await PageObjects.visualize.clickVisType('lens');
+      await PageObjects.lens.goToTimeRange();
+      await PageObjects.lens.switchToVisualization('lnsDatatable');
+
+      // Close immediately
+      await PageObjects.lens.configureDimension({
+        dimension: 'lnsDatatable_metrics > lns-empty-dimension',
+        operation: 'formula',
+        formula: `asdf`,
+      });
+
+      expect(await PageObjects.lens.getErrorCount()).to.eql(1);
+    });
+
+    it('should keep the formula when entering expanded mode', async () => {
+      await PageObjects.visualize.navigateToNewVisualization();
+      await PageObjects.visualize.clickVisType('lens');
+      await PageObjects.lens.goToTimeRange();
+      await PageObjects.lens.switchToVisualization('lnsDatatable');
+
+      // Close immediately
+      await PageObjects.lens.configureDimension({
+        dimension: 'lnsDatatable_metrics > lns-empty-dimension',
+        operation: 'formula',
+        formula: `count()`,
+        keepOpen: true,
+      });
+
+      await PageObjects.lens.toggleFullscreen();
+
+      const element = await find.byCssSelector('.monaco-editor');
+      expect(await element.getVisibleText()).to.equal('count()');
+    });
+
+    it('should allow an empty formula combined with a valid formula', async () => {
+      await PageObjects.visualize.navigateToNewVisualization();
+      await PageObjects.visualize.clickVisType('lens');
+      await PageObjects.lens.goToTimeRange();
+      await PageObjects.lens.switchToVisualization('lnsDatatable');
+
+      await PageObjects.lens.configureDimension({
+        dimension: 'lnsDatatable_metrics > lns-empty-dimension',
+        operation: 'formula',
+        formula: `count()`,
+      });
+      await PageObjects.lens.configureDimension({
+        dimension: 'lnsDatatable_metrics > lns-empty-dimension',
+        operation: 'formula',
+      });
+
+      await PageObjects.header.waitUntilLoadingHasFinished();
+      expect(await PageObjects.lens.getErrorCount()).to.eql(0);
+    });
+
+    it('should duplicate a moving average formula and be a valid table', async () => {
+      await PageObjects.visualize.navigateToNewVisualization();
+      await PageObjects.visualize.clickVisType('lens');
+      await PageObjects.lens.goToTimeRange();
+      await PageObjects.lens.switchToVisualization('lnsDatatable');
+
+      await PageObjects.lens.configureDimension({
+        dimension: 'lnsDatatable_rows > lns-empty-dimension',
+        operation: 'date_histogram',
+        field: '@timestamp',
+      });
+
+      await PageObjects.lens.configureDimension({
+        dimension: 'lnsDatatable_metrics > lns-empty-dimension',
+        operation: 'formula',
+        formula: `moving_average(sum(bytes), window=5`,
+        keepOpen: true,
+      });
+      await PageObjects.lens.closeDimensionEditor();
+
+      await PageObjects.lens.dragDimensionToDimension(
+        'lnsDatatable_metrics > lns-dimensionTrigger',
+        'lnsDatatable_metrics > lns-empty-dimension'
+      );
+      expect(await PageObjects.lens.getDatatableCellText(1, 1)).to.eql('222420');
+      expect(await PageObjects.lens.getDatatableCellText(1, 2)).to.eql('222420');
+    });
+
+    it('should keep the formula if the user does not fully transition to a quick function', async () => {
+      await PageObjects.visualize.navigateToNewVisualization();
+      await PageObjects.visualize.clickVisType('lens');
+      await PageObjects.lens.goToTimeRange();
+      await PageObjects.lens.switchToVisualization('lnsDatatable');
+
+      await PageObjects.lens.configureDimension({
+        dimension: 'lnsDatatable_metrics > lns-empty-dimension',
+        operation: 'formula',
+        formula: `count()`,
+        keepOpen: true,
+      });
+
+      await PageObjects.lens.switchToQuickFunctions();
+      await testSubjects.click(`lns-indexPatternDimension-min incompatible`);
+      await PageObjects.common.sleep(1000);
+      await PageObjects.lens.closeDimensionEditor();
+
+      expect(await PageObjects.lens.getDimensionTriggerText('lnsDatatable_metrics', 0)).to.eql(
+        'count()'
+      );
+    });
+  });
+}
diff --git a/x-pack/test/functional/apps/lens/index.ts b/x-pack/test/functional/apps/lens/index.ts
index 1efceace8b167..99b75bdabe6c4 100644
--- a/x-pack/test/functional/apps/lens/index.ts
+++ b/x-pack/test/functional/apps/lens/index.ts
@@ -41,6 +41,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
       loadTestFile(require.resolve('./geo_field'));
       loadTestFile(require.resolve('./lens_reporting'));
       loadTestFile(require.resolve('./lens_tagging'));
+      loadTestFile(require.resolve('./formula'));
 
       // has to be last one in the suite because it overrides saved objects
       loadTestFile(require.resolve('./rollup'));
diff --git a/x-pack/test/functional/apps/lens/smokescreen.ts b/x-pack/test/functional/apps/lens/smokescreen.ts
index 2a4d56bbea791..5d775f154c943 100644
--- a/x-pack/test/functional/apps/lens/smokescreen.ts
+++ b/x-pack/test/functional/apps/lens/smokescreen.ts
@@ -172,10 +172,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
 
       await testSubjects.existOrFail('indexPattern-dimension-formatDecimals');
 
+      await PageObjects.lens.closeDimensionEditor();
+
       expect(await PageObjects.lens.getDimensionTriggerText('lnsXY_yDimensionPanel')).to.eql(
         'Test of label'
       );
-      await PageObjects.lens.closeDimensionEditor();
     });
 
     it('should be able to add very long labels and still be able to remove a dimension', async () => {
@@ -587,6 +588,57 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
       );
     });
 
+    it('should not leave an incomplete column in the visualization config with field-based operation', async () => {
+      await PageObjects.visualize.navigateToNewVisualization();
+      await PageObjects.visualize.clickVisType('lens');
+      await PageObjects.lens.goToTimeRange();
+
+      await PageObjects.lens.configureDimension({
+        dimension: 'lnsXY_yDimensionPanel > lns-empty-dimension',
+        operation: 'min',
+      });
+
+      expect(await PageObjects.lens.getDimensionTriggerText('lnsXY_yDimensionPanel')).to.eql(
+        undefined
+      );
+    });
+
+    it('should not leave an incomplete column in the visualization config with reference-based operations', async () => {
+      await PageObjects.visualize.navigateToNewVisualization();
+      await PageObjects.visualize.clickVisType('lens');
+      await PageObjects.lens.goToTimeRange();
+
+      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: 'moving_average',
+        field: 'Records',
+      });
+
+      expect(await PageObjects.lens.getDimensionTriggerText('lnsXY_yDimensionPanel')).to.eql(
+        'Moving average of Count of records'
+      );
+
+      await PageObjects.lens.configureDimension({
+        dimension: 'lnsXY_yDimensionPanel > lns-dimensionTrigger',
+        operation: 'median',
+        isPreviousIncompatible: true,
+        keepOpen: true,
+      });
+
+      expect(await PageObjects.lens.isDimensionEditorOpen()).to.eql(true);
+
+      await PageObjects.lens.closeDimensionEditor();
+
+      expect(await PageObjects.lens.getDimensionTriggerText('lnsXY_yDimensionPanel')).to.eql(
+        undefined
+      );
+    });
+
     it('should transition from unique count to last value', async () => {
       await PageObjects.visualize.navigateToNewVisualization();
       await PageObjects.visualize.clickVisType('lens');
diff --git a/x-pack/test/functional/apps/observability/feature_controls/index.ts b/x-pack/test/functional/apps/observability/feature_controls/index.ts
new file mode 100644
index 0000000000000..53fba57413443
--- /dev/null
+++ b/x-pack/test/functional/apps/observability/feature_controls/index.ts
@@ -0,0 +1,15 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { FtrProviderContext } from '../../../ftr_provider_context';
+
+export default function ({ loadTestFile }: FtrProviderContext) {
+  describe('feature controls', function () {
+    this.tags('skipFirefox');
+    loadTestFile(require.resolve('./observability_security'));
+  });
+}
diff --git a/x-pack/test/functional/apps/observability/feature_controls/observability_security.ts b/x-pack/test/functional/apps/observability/feature_controls/observability_security.ts
new file mode 100644
index 0000000000000..d27f1acdd3e31
--- /dev/null
+++ b/x-pack/test/functional/apps/observability/feature_controls/observability_security.ts
@@ -0,0 +1,216 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import expect from '@kbn/expect';
+import { FtrProviderContext } from '../../../ftr_provider_context';
+
+export default function ({ getPageObjects, getService }: FtrProviderContext) {
+  const esArchiver = getService('esArchiver');
+  const security = getService('security');
+  const PageObjects = getPageObjects([
+    'common',
+    'observability',
+    'error',
+    'security',
+    'spaceSelector',
+  ]);
+  const appsMenu = getService('appsMenu');
+  const testSubjects = getService('testSubjects');
+  describe('observability security feature controls', function () {
+    this.tags(['skipFirefox']);
+    before(async () => {
+      await esArchiver.load('x-pack/test/functional/es_archives/cases/default');
+    });
+
+    after(async () => {
+      await esArchiver.unload('x-pack/test/functional/es_archives/cases/default');
+    });
+
+    describe('observability cases all privileges', () => {
+      before(async () => {
+        await security.role.create('cases_observability_all_role', {
+          elasticsearch: { cluster: [], indices: [], run_as: [] },
+          kibana: [
+            { spaces: ['*'], base: [], feature: { observabilityCases: ['all'], logs: ['all'] } },
+          ],
+        });
+
+        await security.user.create('cases_observability_all_user', {
+          password: 'cases_observability_all_user-password',
+          roles: ['cases_observability_all_role'],
+          full_name: 'test user',
+        });
+
+        await PageObjects.security.forceLogout();
+
+        await PageObjects.security.login(
+          'cases_observability_all_user',
+          'cases_observability_all_user-password',
+          {
+            expectSpaceSelector: false,
+          }
+        );
+      });
+
+      after(async () => {
+        await PageObjects.security.forceLogout();
+        await Promise.all([
+          security.role.delete('cases_observability_all_role'),
+          security.user.delete('cases_observability_all_user'),
+        ]);
+      });
+
+      it('shows observability/cases navlink', async () => {
+        const navLinks = (await appsMenu.readLinks()).map((link) => link.text).slice(0, 2);
+        expect(navLinks).to.eql(['Overview', 'Cases']);
+      });
+
+      it(`landing page shows "Create new case" button`, async () => {
+        await PageObjects.common.navigateToActualUrl('observabilityCases');
+        await PageObjects.observability.expectCreateCaseButtonEnabled();
+      });
+
+      it(`doesn't show read-only badge`, async () => {
+        await PageObjects.observability.expectNoReadOnlyCallout();
+      });
+
+      it(`allows a case to be created`, async () => {
+        await PageObjects.common.navigateToActualUrl('observabilityCases');
+
+        await testSubjects.click('createNewCaseBtn');
+
+        await PageObjects.observability.expectCreateCase();
+      });
+
+      it(`allows a case to be edited`, async () => {
+        await PageObjects.common.navigateToUrl(
+          'observabilityCases',
+          '4c32e6b0-c3c5-11eb-b389-3fadeeafa60f',
+          {
+            shouldUseHashForSubUrl: false,
+          }
+        );
+        await PageObjects.observability.expectAddCommentButton();
+      });
+    });
+
+    describe('observability cases read-only privileges', () => {
+      before(async () => {
+        await security.role.create('cases_observability_read_role', {
+          elasticsearch: { cluster: [], indices: [], run_as: [] },
+          kibana: [
+            {
+              spaces: ['*'],
+              base: [],
+              feature: { observabilityCases: ['read'], logs: ['all'] },
+            },
+          ],
+        });
+
+        await security.user.create('cases_observability_read_user', {
+          password: 'cases_observability_read_user-password',
+          roles: ['cases_observability_read_role'],
+          full_name: 'test user',
+        });
+
+        await PageObjects.security.login(
+          'cases_observability_read_user',
+          'cases_observability_read_user-password',
+          {
+            expectSpaceSelector: false,
+          }
+        );
+      });
+
+      after(async () => {
+        await security.role.delete('cases_observability_read_role');
+        await security.user.delete('cases_observability_read_user');
+      });
+
+      it('shows observability/cases navlink', async () => {
+        const navLinks = (await appsMenu.readLinks()).map((link) => link.text).slice(0, 2);
+        expect(navLinks).to.eql(['Overview', 'Cases']);
+      });
+
+      it(`landing page shows disabled "Create new case" button`, async () => {
+        await PageObjects.common.navigateToActualUrl('observabilityCases');
+        await PageObjects.observability.expectCreateCaseButtonDisabled();
+      });
+
+      it(`shows read-only callout`, async () => {
+        await PageObjects.observability.expectReadOnlyCallout();
+      });
+
+      it(`does not allow a case to be created`, async () => {
+        await PageObjects.common.navigateToUrl('observabilityCases', 'create', {
+          shouldUseHashForSubUrl: false,
+        });
+
+        // expect redirection to observability cases landing
+        await PageObjects.observability.expectCreateCaseButtonDisabled();
+      });
+
+      it(`does not allow a case to be edited`, async () => {
+        await PageObjects.common.navigateToUrl(
+          'observabilityCases',
+          '4c32e6b0-c3c5-11eb-b389-3fadeeafa60f',
+          {
+            shouldUseHashForSubUrl: false,
+          }
+        );
+        await PageObjects.observability.expectAddCommentButtonDisabled();
+      });
+    });
+
+    describe('no observability privileges', () => {
+      before(async () => {
+        await security.role.create('no_observability_privileges_role', {
+          elasticsearch: { cluster: [], indices: [], run_as: [] },
+          kibana: [
+            {
+              feature: {
+                discover: ['all'],
+              },
+              spaces: ['*'],
+            },
+          ],
+        });
+
+        await security.user.create('no_observability_privileges_user', {
+          password: 'no_observability_privileges_user-password',
+          roles: ['no_observability_privileges_role'],
+          full_name: 'test user',
+        });
+
+        await PageObjects.security.login(
+          'no_observability_privileges_user',
+          'no_observability_privileges_user-password',
+          {
+            expectSpaceSelector: false,
+          }
+        );
+      });
+
+      after(async () => {
+        await security.role.delete('no_observability_privileges_role');
+        await security.user.delete('no_observability_privileges_user');
+      });
+
+      it(`returns a 403`, async () => {
+        await PageObjects.common.navigateToActualUrl('observabilityCases');
+        await PageObjects.observability.expectForbidden();
+      });
+
+      it.skip(`create new case returns a 403`, async () => {
+        await PageObjects.common.navigateToUrl('observabilityCases', 'create', {
+          shouldUseHashForSubUrl: false,
+        });
+        await PageObjects.observability.expectForbidden();
+      });
+    });
+  });
+}
diff --git a/x-pack/test/functional/apps/observability/index.ts b/x-pack/test/functional/apps/observability/index.ts
new file mode 100644
index 0000000000000..b7f03b5f27bae
--- /dev/null
+++ b/x-pack/test/functional/apps/observability/index.ts
@@ -0,0 +1,15 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { FtrProviderContext } from '../../ftr_provider_context';
+
+export default function ({ loadTestFile }: FtrProviderContext) {
+  describe('Observability specs', function () {
+    this.tags('ciGroup6');
+    loadTestFile(require.resolve('./feature_controls'));
+  });
+}
diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js
index 20487047a3a56..2679bb55ad341 100644
--- a/x-pack/test/functional/config.js
+++ b/x-pack/test/functional/config.js
@@ -60,6 +60,7 @@ export default async function ({ readConfigFile }) {
       resolve(__dirname, './apps/reporting_management'),
       resolve(__dirname, './apps/management'),
       resolve(__dirname, './apps/reporting'),
+      resolve(__dirname, './apps/observability'),
 
       // This license_management file must be last because it is destructive.
       resolve(__dirname, './apps/license_management'),
@@ -94,6 +95,7 @@ export default async function ({ readConfigFile }) {
         '--xpack.discoverEnhanced.actions.exploreDataInContextMenu.enabled=true',
         '--timelion.ui.enabled=true',
         '--savedObjects.maxImportPayloadBytes=10485760', // for OSS test management/_import_objects
+        '--xpack.observability.unsafe.cases.enabled=true',
       ],
     },
     uiSettings: {
diff --git a/x-pack/test/functional/es_archives/cases/default/data.json.gz b/x-pack/test/functional/es_archives/cases/default/data.json.gz
new file mode 100644
index 0000000000000..9ec4efad4bdfc
Binary files /dev/null and b/x-pack/test/functional/es_archives/cases/default/data.json.gz differ
diff --git a/x-pack/test/functional/es_archives/cases/default/mappings.json b/x-pack/test/functional/es_archives/cases/default/mappings.json
new file mode 100644
index 0000000000000..28d9daff50d94
--- /dev/null
+++ b/x-pack/test/functional/es_archives/cases/default/mappings.json
@@ -0,0 +1,322 @@
+{
+  "type": "index",
+  "value": {
+    "aliases": {
+      ".kibana": {
+      }
+    },
+    "index": ".kibana_1",
+    "mappings": {
+      "properties": {
+        "cases": {
+          "properties": {
+            "closed_at": {
+              "type": "date"
+            },
+            "closed_by": {
+              "properties": {
+                "username": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                }
+              }
+            },
+            "connector": {
+              "properties": {
+                "fields": {
+                  "properties": {
+                    "key": {
+                      "fields": {
+                        "keyword": {
+                          "ignore_above": 256,
+                          "type": "keyword"
+                        }
+                      },
+                      "type": "text"
+                    },
+                    "value": {
+                      "fields": {
+                        "keyword": {
+                          "ignore_above": 256,
+                          "type": "keyword"
+                        }
+                      },
+                      "type": "text"
+                    }
+                  }
+                },
+                "id": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                },
+                "name": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                },
+                "type": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                }
+              }
+            },
+            "created_at": {
+              "type": "date"
+            },
+            "created_by": {
+              "properties": {
+                "email": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                },
+                "full_name": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                },
+                "username": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                }
+              }
+            },
+            "description": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            },
+            "external_service": {
+              "properties": {
+                "connector_id": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                },
+                "connector_name": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                },
+                "external_id": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                },
+                "external_title": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                },
+                "external_url": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                },
+                "pushed_at": {
+                  "type": "date"
+                },
+                "pushed_by": {
+                  "properties": {
+                    "username": {
+                      "fields": {
+                        "keyword": {
+                          "ignore_above": 256,
+                          "type": "keyword"
+                        }
+                      },
+                      "type": "text"
+                    }
+                  }
+                }
+              }
+            },
+            "owner": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            },
+            "settings": {
+              "properties": {
+                "syncAlerts": {
+                  "type": "boolean"
+                }
+              }
+            },
+            "status": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            },
+            "tags": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            },
+            "title": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            },
+            "type": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            },
+            "updated_at": {
+              "type": "date"
+            },
+            "updated_by": {
+              "properties": {
+                "email": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                },
+                "full_name": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                },
+                "username": {
+                  "fields": {
+                    "keyword": {
+                      "ignore_above": 256,
+                      "type": "keyword"
+                    }
+                  },
+                  "type": "text"
+                }
+              }
+            }
+          }
+        },
+        "coreMigrationVersion": {
+          "fields": {
+            "keyword": {
+              "ignore_above": 256,
+              "type": "keyword"
+            }
+          },
+          "type": "text"
+        },
+        "migrationVersion": {
+          "properties": {
+            "cases": {
+              "fields": {
+                "keyword": {
+                  "ignore_above": 256,
+                  "type": "keyword"
+                }
+              },
+              "type": "text"
+            }
+          }
+        },
+        "type": {
+          "fields": {
+            "keyword": {
+              "ignore_above": 256,
+              "type": "keyword"
+            }
+          },
+          "type": "text"
+        },
+        "updated_at": {
+          "type": "date"
+        }
+      }
+    },
+    "settings": {
+      "index": {
+        "auto_expand_replicas": "0-1",
+        "number_of_replicas": "1",
+        "number_of_shards": "1"
+      }
+    }
+  }
+}
diff --git a/x-pack/test/functional/page_objects/index.ts b/x-pack/test/functional/page_objects/index.ts
index a362fd7e4b7c2..5c3d9b680fc41 100644
--- a/x-pack/test/functional/page_objects/index.ts
+++ b/x-pack/test/functional/page_objects/index.ts
@@ -16,6 +16,7 @@ import { GrokDebuggerPageObject } from './grok_debugger_page';
 import { WatcherPageObject } from './watcher_page';
 import { ReportingPageObject } from './reporting_page';
 import { AccountSettingsPageObject } from './account_settings_page';
+import { ObservabilityPageProvider } from './observability_page';
 import { InfraHomePageProvider } from './infra_home_page';
 import { InfraLogsPageProvider } from './infra_logs_page';
 import { GisPageObject } from './gis_page';
@@ -82,4 +83,5 @@ export const pageObjects = {
   navigationalSearch: NavigationalSearchPageObject,
   banners: BannersPageObject,
   detections: DetectionsPageObject,
+  observability: ObservabilityPageProvider,
 };
diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts
index c0111afad2893..b2790d0f7a08e 100644
--- a/x-pack/test/functional/page_objects/lens_page.ts
+++ b/x-pack/test/functional/page_objects/lens_page.ts
@@ -42,6 +42,10 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont
       return await testSubjects.findAll('lnsFieldListPanelField');
     },
 
+    async isLensPageOrFail() {
+      return await testSubjects.existOrFail('lnsApp');
+    },
+
     /**
      * Move the date filter to the specified time range, defaults to
      * a range that has data in our dataset.
@@ -88,7 +92,10 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont
      * @param title - the title of the list item to be clicked
      */
     clickVisualizeListItemTitle(title: string) {
-      return testSubjects.click(`visListingTitleLink-${title}`);
+      return retry.try(async () => {
+        await testSubjects.click(`visListingTitleLink-${title}`);
+        await this.isLensPageOrFail();
+      });
     },
 
     /**
@@ -107,6 +114,7 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont
         isPreviousIncompatible?: boolean;
         keepOpen?: boolean;
         palette?: string;
+        formula?: string;
       },
       layerIndex = 0
     ) {
@@ -114,10 +122,15 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont
         await testSubjects.click(`lns-layerPanel-${layerIndex} > ${opts.dimension}`);
         await testSubjects.exists(`lns-indexPatternDimension-${opts.operation}`);
       });
-      const operationSelector = opts.isPreviousIncompatible
-        ? `lns-indexPatternDimension-${opts.operation} incompatible`
-        : `lns-indexPatternDimension-${opts.operation}`;
-      await testSubjects.click(operationSelector);
+
+      if (opts.operation === 'formula') {
+        await this.switchToFormula();
+      } else {
+        const operationSelector = opts.isPreviousIncompatible
+          ? `lns-indexPatternDimension-${opts.operation} incompatible`
+          : `lns-indexPatternDimension-${opts.operation}`;
+        await testSubjects.click(operationSelector);
+      }
 
       if (opts.field) {
         const target = await testSubjects.find('indexPattern-dimension-field');
@@ -125,6 +138,10 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont
         await comboBox.setElement(target, opts.field);
       }
 
+      if (opts.formula) {
+        await this.typeFormula(opts.formula);
+      }
+
       if (opts.palette) {
         await this.setPalette(opts.palette);
       }
@@ -357,7 +374,7 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont
       await retry.try(async () => {
         await testSubjects.click('lns-palettePicker');
         const currentPalette = await (
-          await find.byCssSelector('[aria-selected=true]')
+          await find.byCssSelector('[role=option][aria-selected=true]')
         ).getAttribute('id');
         expect(currentPalette).to.equal(palette);
       });
@@ -379,6 +396,18 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont
       });
     },
 
+    async isDimensionEditorOpen() {
+      return await testSubjects.exists('lns-indexPattern-dimensionContainerBack');
+    },
+
+    // closes the dimension editor flyout
+    async closeDimensionEditor() {
+      await retry.try(async () => {
+        await testSubjects.click('lns-indexPattern-dimensionContainerBack');
+        await testSubjects.missingOrFail('lns-indexPattern-dimensionContainerBack');
+      });
+    },
+
     async enableTimeShift() {
       await testSubjects.click('indexPattern-advanced-popover');
       await retry.try(async () => {
@@ -398,14 +427,6 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont
       await testSubjects.click('errorFixAction');
     },
 
-    // closes the dimension editor flyout
-    async closeDimensionEditor() {
-      await retry.try(async () => {
-        await testSubjects.click('lns-indexPattern-dimensionContainerBack');
-        await testSubjects.missingOrFail('lns-indexPattern-dimensionContainerBack');
-      });
-    },
-
     async isTopLevelAggregation() {
       return await testSubjects.isEuiSwitchChecked('indexPattern-nesting-switch');
     },
@@ -549,7 +570,8 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont
         });
       }
       const errors = await testSubjects.findAll('configuration-failure-error');
-      return errors?.length ?? 0;
+      const expressionErrors = await testSubjects.findAll('expression-failure');
+      return (errors?.length ?? 0) + (expressionErrors?.length ?? 0);
     },
 
     async searchOnChartSwitch(subVisualizationId: string, searchTerm?: string) {
@@ -1025,5 +1047,27 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont
       );
       await PageObjects.header.waitUntilLoadingHasFinished();
     },
+
+    async switchToQuickFunctions() {
+      await testSubjects.click('lens-dimensionTabs-quickFunctions');
+    },
+
+    async switchToFormula() {
+      await testSubjects.click('lens-dimensionTabs-formula');
+    },
+
+    async toggleFullscreen() {
+      await testSubjects.click('lnsFormula-fullscreen');
+    },
+
+    async typeFormula(formula: string) {
+      // Formula takes time to open
+      await PageObjects.common.sleep(500);
+      await find.byCssSelector('.monaco-editor');
+      await find.clickByCssSelectorWhenNotDisabled('.monaco-editor');
+      const input = await find.activeElement();
+      await input.clearValueWithKeyboard();
+      await input.type(formula);
+    },
   });
 }
diff --git a/x-pack/test/functional/page_objects/observability_page.ts b/x-pack/test/functional/page_objects/observability_page.ts
new file mode 100644
index 0000000000000..95016c31d1054
--- /dev/null
+++ b/x-pack/test/functional/page_objects/observability_page.ts
@@ -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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import expect from '@kbn/expect';
+
+import { FtrProviderContext } from '../ftr_provider_context';
+
+export function ObservabilityPageProvider({ getService, getPageObjects }: FtrProviderContext) {
+  const testSubjects = getService('testSubjects');
+  const find = getService('find');
+
+  return {
+    async expectCreateCaseButtonEnabled() {
+      const button = await testSubjects.find('createNewCaseBtn', 20000);
+      const disabledAttr = await button.getAttribute('disabled');
+      expect(disabledAttr).to.be(null);
+    },
+
+    async expectCreateCaseButtonDisabled() {
+      const button = await testSubjects.find('createNewCaseBtn', 20000);
+      const disabledAttr = await button.getAttribute('disabled');
+      expect(disabledAttr).to.be('true');
+    },
+
+    async expectReadOnlyCallout() {
+      await testSubjects.existOrFail('case-callout-e41900b01c9ef0fa81dd6ff326083fb3');
+    },
+
+    async expectNoReadOnlyCallout() {
+      await testSubjects.missingOrFail('case-callout-e41900b01c9ef0fa81dd6ff326083fb3');
+    },
+
+    async expectCreateCase() {
+      await testSubjects.existOrFail('case-creation-form-steps');
+    },
+
+    async expectAddCommentButton() {
+      const button = await testSubjects.find('submit-comment', 20000);
+      const disabledAttr = await button.getAttribute('disabled');
+      expect(disabledAttr).to.be(null);
+    },
+
+    async expectAddCommentButtonDisabled() {
+      const button = await testSubjects.find('submit-comment', 20000);
+      const disabledAttr = await button.getAttribute('disabled');
+      expect(disabledAttr).to.be('true');
+    },
+
+    async expectForbidden() {
+      const h2 = await find.byCssSelector('body', 20000);
+      const text = await h2.getVisibleText();
+      expect(text).to.contain('Kibana feature privileges required');
+    },
+  };
+}
diff --git a/x-pack/test/functional/page_objects/security_page.ts b/x-pack/test/functional/page_objects/security_page.ts
index 437749d31c15e..85382465d974e 100644
--- a/x-pack/test/functional/page_objects/security_page.ts
+++ b/x-pack/test/functional/page_objects/security_page.ts
@@ -207,10 +207,7 @@ export class SecurityPageObject extends FtrService {
     }
 
     if (expectedResult === 'chrome') {
-      await this.find.byCssSelector(
-        '[data-test-subj="kibanaChrome"] .kbnAppWrapper:not(.kbnAppWrapper--hiddenChrome)',
-        20000
-      );
+      await this.find.byCssSelector('[data-test-subj="userMenuButton"]', 20000);
       this.log.debug(`Finished login process currentUrl = ${await this.browser.getCurrentUrl()}`);
     }
   }
diff --git a/x-pack/test/functional_with_es_ssl/apps/ml/alert_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/ml/alert_flyout.ts
index 0f5e12f226c0e..96e6bd4b302bd 100644
--- a/x-pack/test/functional_with_es_ssl/apps/ml/alert_flyout.ts
+++ b/x-pack/test/functional_with_es_ssl/apps/ml/alert_flyout.ts
@@ -67,7 +67,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
 
   let testJobId = '';
 
-  describe('anomaly detection alert', function () {
+  // Failing: See https://github.com/elastic/kibana/issues/102012
+  describe.skip('anomaly detection alert', function () {
     this.tags('ciGroup13');
 
     before(async () => {
diff --git a/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts
index a631bf3781d09..7d235d9e18108 100644
--- a/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts
+++ b/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts
@@ -6,11 +6,12 @@
  */
 
 import expect from '@kbn/expect';
+import { delay } from 'bluebird';
+
 import { FtrProviderContext } from '../../ftr_provider_context';
 
 export default ({ getPageObjects, getService }: FtrProviderContext) => {
-  // FLAKY: https://github.com/elastic/kibana/issues/88177
-  describe.skip('uptime alerts', () => {
+  describe('uptime alerts', () => {
     const pageObjects = getPageObjects(['common', 'uptime']);
     const supertest = getService('supertest');
     const retry = getService('retry');
@@ -91,11 +92,13 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
         // put the fetch code in a retry block with a timeout.
         let alert: any;
         await retry.tryForTime(60 * 1000, async () => {
+          // add a delay before next call to not overload the server
+          await delay(1500);
           const apiResponse = await supertest.get('/api/alerts/_find?search=uptime-test');
           const alertsFromThisTest = apiResponse.body.data.filter(
             ({ name }: { name: string }) => name === 'uptime-test'
           );
-          expect(alertsFromThisTest).to.have.length(1);
+          expect(alertsFromThisTest.length >= 1).to.be(true);
           alert = alertsFromThisTest[0];
         });
 
@@ -124,7 +127,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
           expect(timerangeUnit).to.be('h');
           expect(timerangeCount).to.be(1);
           expect(JSON.stringify(filters)).to.eql(
-            `{"url.port":["5678"],"observer.geo.name":["mpls"],"monitor.type":["http"],"tags":[]}`
+            `{"tags":[],"url.port":["5678"],"observer.geo.name":["mpls"],"monitor.type":["http"]}`
           );
         } finally {
           await supertest.delete(`/api/alerts/alert/${id}`).set('kbn-xsrf', 'true').expect(204);
diff --git a/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/public/plugin.ts b/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/public/plugin.ts
index 48a3aca742c72..fc51740e82900 100644
--- a/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/public/plugin.ts
+++ b/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/public/plugin.ts
@@ -8,7 +8,7 @@
 import React from 'react';
 import { Plugin, CoreSetup, AppMountParameters } from 'kibana/public';
 import { PluginSetupContract as AlertingSetup } from '../../../../../../plugins/alerting/public';
-import { AlertType, SanitizedAlert } from '../../../../../../plugins/alerting/common';
+import { SanitizedAlert } from '../../../../../../plugins/alerting/common';
 import { TriggersAndActionsUIPublicPluginSetup } from '../../../../../../plugins/triggers_actions_ui/public';
 
 export type Setup = void;
@@ -24,7 +24,7 @@ export class AlertingFixturePlugin implements Plugin<Setup, Start, AlertingExamp
     alerting.registerNavigation(
       'alerting_fixture',
       'test.noop',
-      (alert: SanitizedAlert, alertType: AlertType) => `/rule/${alert.id}`
+      (alert: SanitizedAlert) => `/rule/${alert.id}`
     );
 
     triggersActionsUi.alertTypeRegistry.register({
diff --git a/x-pack/test/security_functional/tests/oidc/url_capture.ts b/x-pack/test/security_functional/tests/oidc/url_capture.ts
index 4c6b68cc3757c..706189dcb5a2a 100644
--- a/x-pack/test/security_functional/tests/oidc/url_capture.ts
+++ b/x-pack/test/security_functional/tests/oidc/url_capture.ts
@@ -43,10 +43,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
         deployment.getHostPort() + '/app/management/security/users#some=hash-value'
       );
 
-      await find.byCssSelector(
-        '[data-test-subj="kibanaChrome"] .kbnAppWrapper:not(.kbnAppWrapper--hiddenChrome)',
-        20000
-      );
+      await find.byCssSelector('[data-test-subj="userMenuButton"]', 20000);
 
       // We need to make sure that both path and hash are respected.
       const currentURL = parse(await browser.getCurrentUrl());
diff --git a/x-pack/test/security_functional/tests/saml/url_capture.ts b/x-pack/test/security_functional/tests/saml/url_capture.ts
index 65d7688472539..2b0b8690ebab6 100644
--- a/x-pack/test/security_functional/tests/saml/url_capture.ts
+++ b/x-pack/test/security_functional/tests/saml/url_capture.ts
@@ -43,10 +43,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
         deployment.getHostPort() + '/app/management/security/users#some=hash-value'
       );
 
-      await find.byCssSelector(
-        '[data-test-subj="kibanaChrome"] .kbnAppWrapper:not(.kbnAppWrapper--hiddenChrome)',
-        20000
-      );
+      await find.byCssSelector('[data-test-subj="userMenuButton"]', 20000);
 
       // We need to make sure that both path and hash are respected.
       const currentURL = parse(await browser.getCurrentUrl());