## Summary
Fixes https://github.com/elastic/security-team/issues/8934
Summarize your PR. If it involves visual changes include a screenshot or
gif.
This PR enables the Security AI assistant to be used globally - i.e. if
you are outside of the security solution (e.g. Discover), the Security
Assistant can still be opened.
Changes:
- A public module has been added to the elastic-assistant plugin
(previously it was a server-side-only plugin).
- The vast majority of the assistant (flyout and nav bar) has been moved
into the new elastic-assistantpublic plugin.
- Comment actions & message augmentations remain within the
security-solution.
- A new public plugin was created called elastic-assistant-shared state.
This plugin is used to share state between the elastic-assistant public
plugin and other plugins (e.g. security-solution).
- For example, the security solution registers comment actions in the
elastic-assistant-shared-state plugin. The elastic-assistant public
plugin then reads the comment actions from
elastic-assistant-shared-state and renders them in the assistant flyout.

### Considerations:
- Currently, the Security AI assistant is being displayed everywhere
except the observability solution (see implementation
[here](https://github.com/elastic/kibana/pull/223936/files#diff-5dd1ea91c2d5d242203cc58ee59ec283116e5e739ed82bae4e2cd78af322150c)).
This is only for testing while the PR is in review. We plan to add a
setting to the stack management that allows the user to configure where
they would like the assistant to be shown. This will be changed before
the PR is merged.
## How to test
Feel free to use the cloud and serverless deployments created by the CI
pipeline for testing. Credentials can be found on Buildkite.
### Verify that the Security AI assistant works as expected within the
security solution
Expected there to be no changes in how the security AI assistant works
within the Security Solution. Please do some exploratory testing to make
sure nothing has changed.
Start the branch locally and go to http://localhost:5601/app/security/
Things to test:
- Does the assistant open?
- Can I send an alert to the assistant from the alerts page?
- Does the assistant display code blocks correctly?
- Does the assistant display ESQL correctly (can I view the ESQL in the
timeline)?
- Do assistant messages have the correct comment actions? Do the comment
actions work?
- Are conversations displayed correctly?
- Do citations work?
- Does the assistant work in serverless? Does the assistant work as
expected in AI4SOC?
- Do quick prompts work?
- Can you select a system prompt for a new convo?
- Can you send alerts to the Security AI assistant?
- AI assistant in a space that has Security disabled.
- Does attack discovery work?
AI assistant open in Discover app:
<img width="1841" alt="image"
src="https://github.com/user-attachments/assets/0a13a100-d192-4fa4-b395-0951452e14c2"
/>
AI assistant in Security solution:
<img width="1841" alt="image"
src="https://github.com/user-attachments/assets/7ed38f37-79de-41a7-a80f-8b96147bfdf6"
/>
### Verify the Security AI assistant works in Discover (or anywhere
outside of the Security solution)?
Head over to http://localhost:5601/app/discover. Note that some
functionality is removed when using the AI assistant outside of
security:
- Only the "copy" comment action appears on messages.
- Code block augmentations (i.e. the button that opens ESQL inside of
the timeline) don't appear.
Things to test:
- Does the security AI assistant button appear in the nav bar?
- Can you open the security AI assistant?
- Are you able to send messages?
- Are conversations appearing as expected?
- Can you close the assistant?
- Do citations work?
- Can you switch to a different solution while the assistant is open?
Security AI assistant open in AI4SOC Discover:
<img width="1841" alt="image"
src="https://github.com/user-attachments/assets/36537b9b-e945-459e-ac13-43e9444e92b7"
/>
### Checklist
Check the PR satisfies following conditions.
Reviewers should verify this PR satisfies this list as well.
- [X] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [X]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [X] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [X] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [X] This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.
- [X] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [X] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
### Identify risks
Does this PR introduce any risks? For example, consider risks like hard
to test bugs, performance regression, potential of data loss.
Describe the risk, its severity, and mitigation for each identified
risk. Invite stakeholders and evaluate how to proceed before merging.
- [ ] [See some risk
examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)
- [ ] ...
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
## Summary
- Moved `search_navigation` to `plugins` root
- `search_navigation` being inside the search_solution folder was a
pre-cursor to the solutions/search migration. The introduction of the
solutions/search folder made the search_solution folder redundant,
therefore this migrates the search_navigation plugin up with all the
other search plugins.
- Moved the base classic nav items list to the search_navigation plugin.
The classic nav items are now a static list and can be servered from the
search_navigation plugin instead of being shared from
`enterprise_search`. This is mainly a devx improvement to allow all
search related navigation changes to eventually be maintained in the
search navigation plugin.
### Checklist
- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
## Summary
Follow up to #210579. Close#193683.
This PR removes the deprecated `visualization:useLegacyTimeAxis`
advanced setting and all related code. This setting was previously used
to enable legacy time axis behavior for charts in Lens, Discover,
Visualize and TSVB, but has been deprecated and is no longer needed. All
usage of the setting was already removed in #210579, this PR just cleans
up the advanced setting itself.
## Changes
- Removed the `visualization:useLegacyTimeAxis` UI setting registration
from the charts plugin
- Removed `LEGACY_TIME_AXIS` constant export from charts common module
- Cleaned up related TypeScript configuration dependencies
- Removed telemetry schema entries for the deprecated setting
- Removed translation strings for the deprecated setting
- Adds a saved object migration to remove the setting (see [advanced
settings
migrations](https://docs.elastic.dev/kibana-dev-docs/tutorials/advanced-settings#registering-migrations))
### Identify risks
- Identified that a saved object migration needs to be added for the
removal of the setting. See this
[PR](https://github.com/elastic/kibana/pull/157699) for reference.
- Advanced settings [can be
overridden](https://www.elastic.co/docs/extend/kibana/ui-settings-service#uisettings-overrides)
in `kibana.yml`. If the setting is present in `kibana.yml` and we remove
support for it, if verification of the file was too strict, it would
fail to start Kibana. I verified that Kibana still starts when support
for the advanced setting was removed but it's still present in
`kibana.yml`.
## Release note
Removal of the deprecated `visualization:useLegacyTimeAxis` advanced
setting.
## Summary
* Address https://github.com/elastic/kibana/issues/217145 - Put in place
a check to ensure we're upgrading from Kibana 8.18.0 or newer.
* Address https://github.com/elastic/kibana/issues/220521 - New attempt
at removing the `switchToModelVersionAt` property, inspired on
https://github.com/elastic/kibana/pull/219029.
The previous attempt caused a regression: index meta information started
storing _modelVersions_ that were older than the previously stored ones,
which were defaulting to 10.0.0 for SO types that did NOT define
`modelVersions`.
This was due to the removal of the applyTypeDefaults, which was ensuring
all SOs had the `switchToModelVersionAt` property set.
This flag was then used by
`src/core/packages/saved-objects/base-server-internal/src/model_version/version_map.ts`
to determine whether to use `modelVersions` or the legacy `migrations`
property in order to determine the latest model version for a given
type.
When removing the `switchToModelVersionAt` flag (and its default
backfill), the logic started defaulting to the latest `migrations`
version for those SO types that were not defining any `modelVersion`,
resulting in older versions that those stored in the SO indices. This
caused incident https://elasticco.atlassian.net/browse/INC-3818.
This regression has been shipped in 9.0.0 (the PR was
[backported](https://github.com/elastic/kibana/pull/219329)), so in top
of the cleanup, we now need to address
https://github.com/elastic/kibana/issues/220521 to ensure a smooth
transition _OnPrem => Serverless_.
---------
Co-authored-by: Christiane (Tina) Heiligers <christiane.heiligers@elastic.co>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
## Summary
This PR applies **lossless compression** to all SVG and JPG/PNG assets
across Kibana using:
- [`svgo`](https://github.com/svg/svgo) — for optimizing SVGs
- [`image-optimize`](https://www.npmjs.com/package/image-optimize) — for
JPG/PNG compression
‼️**Please scroll to ''Unknown metric groups" accordion to see what's
the gain for your code.**
<img width="542" alt="Screenshot 2025-06-18 at 13 24 20"
src="https://github.com/user-attachments/assets/191afb28-44fc-4551-9026-756a8385c66a"
/>
The goal is to reduce asset size and improve load performance without
compromising visual quality.
This PR achieves a **23 MB** reduction in asset size across all images
bundled in Kibana’s running code—meaning these compressed images
directly impact what ships in Kibana.
Some assets get bundled into chunks due to our bundling strategy but
might not actually be requested at runtime.
Additionally, I ran the same optimization script on the docs assets as a
harmless extra step, but those savings aren’t included in the 23 MB
total.
---
## Why
While working on Emotion rewrites, I noticed some SVGs seemed
unnecessarily heavy. That led to a broader investigation into our image
assets, and it turns out we’re not consistently optimizing them during
development or build.
---
## Notes
- Visual fidelity of optimized assets has been manually verified — no
visible differences
- The optimization is **lossless**, meaning no quality degradation
- Some assets (like large background images) could benefit further from
**lossy compression**
---
## Follow-ups / Ideas
1. **Automate compression in the dev/build pipeline**
- e.g. add `svgo` as a pre-commit or CI step for SVGs
2. **Improve CI reporting**
- Currently, bundle size diffs for images are hidden under "Unknown
metric groups" in the GitHub CI comment. We may want to make these more
visible.
-
3. **Audit large assets manually** — apply lossy compression where
appropriate
4. **Avoid redundant image loading**
- e.g. background images on the login page are loaded again on the space
selector page since they’re bundled twice. I’m working on a separate PR
to address that.
## Snippets I used to apply the compression
```
# Find SVG files
find . -type f -iname "*.svg" \
-not -path "*/node_modules/*" \
-not -path "*/functional/*" > svg-files.txt
# Compress SVGs
while IFS= read -r file; do
svgo "$file"
done < svg-files.txt
```
This snippet has been used for png and jpg, but the example below is for
png:
```
# Find PNG files
find . -type f -iname "*.png \
-not -path "*/node_modules/*" \
-not -path "*/functional/*" > png-files.txt
# Compress PNGs
while IFS= read -r file; do
image-optimize -f jpg "$file"
done < png-files.txt
```
Address https://github.com/elastic/kibana/issues/216061
Adds an indirection layer in the definition of the `transformFn:`, which
forces devs to explicitly define the types of the documents being
transformed.
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
## Summary
This fixes a few super small issues with the config settings files:
- Fixes an outdated Asciidoc remnant in our "Alert and Actions settings"
PoC file
- Adds a page-level ID in the sample file and the readme
- Fixes up the readme
- Removes unneeded quotation marks from one value in the PoC file.
# Summary
This PR merges Threat Intelligence plugin with security solution, in
order to remove duplicated and unnecessary code introduced as a bridge
between the TI plugin and Security Solution + to simpify maintenance. No
new functionality is implemented here, other than changing imports and
some dependendies to use security solution code directly, without weird
bridges or hacks / indirections.
## Testing
Navigate to threat intelligence plugin / indicators and try clicking
around. It is hard to list every feature we have there
but in general it should work without errors.
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
/!\ Merge on release day
This PR adds release notes for the 9.0.2 release of Kibana.
Please check that listed items are correct and that nothing major is
missing.
Closes: https://github.com/elastic/platform-docs-team/issues/680
---------
Co-authored-by: wajihaparvez <wajiha.parvez@elastic.co>
## Summary
Implements the onechat tool registry RFC.
Fix https://github.com/elastic/search-team/issues/9938
Fix https://github.com/elastic/search-team/issues/10019
This PR introduces the following artifacts:
**plugins:**
- `onechat`
**packages:**
- `@kbn/onechat-common`
- `@kbn/onechat-server`
- `@kbn/onechat-browser`
## Tool APIs overview
### Registering a tool
```ts
class MyPlugin {
setup(core: CoreSetup, { onechat }: { onechat: OnechatPluginSetup }) {
onechat.tools.register({
id: 'my_tool',
name: 'My Tool',
description: 'My very first tool',
meta: {
tags: ['foo', 'bar'],
},
schema: z.object({
someNumber: z.number().describe('Some random number'),
}),
handler: ({ someNumber }, context) => {
return 42 + someNumber;
},
});
}
}
```
### Executing a tool
Using the `execute` API:
```ts
const { result } = await onechat.tools.execute({
toolId: 'my_tool',
toolParams: { someNumber: 9000 },
request,
});
```
Using a tool descriptor:
```ts
const tool = await onechat.tools.registry.get({ toolId: 'my_tool', request });
const { result } = await tool.execute({ toolParams: { someNumber: 9000 } });
```
With error handling:
```ts
import { isToolNotFoundError } from '@kbn/onechat-common';
try {
const { result } = await onechat.tools.execute({
toolId: 'my_tool',
toolParams: { someNumber: 9000 },
request,
});
} catch (e) {
if (isToolNotFoundError(e)) {
throw new Error(`run ${e.meta.runId} failed because tool was not found`);
}
}
```
### Listing tools
```ts
const tools = await onechat.tools.registry.list({ request });
```
*More details and example in the plugin's readme.*
### What is **not** included in this PR:
- tool access control / authorization - we have a dedicated RFC
- dynamic tool registration / permissions checks part/of depends on the
authorization RFC
- feature / capabilities - will come with browser-side and HTTP APIs
- fully defining tool meta - hard to do now
- filter parameters for the tool list API - depends on the meta being
defined
*Those will be follow-ups*. Everything else from the RFC should be
there.
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This outdated settings file could cause some confusion so let's remove
it.
The newer `kibana-alert-action-settings.yml` will be used to generated
settings docs.
## Summary
This PR aims to answer questions about the implementation details for
https://github.com/elastic/kibana-team/issues/1328
We'd like to trigger an intercept dialog to users at specific time
intervals that vary and depend on different parameters, see the PRD
linked in the aforementioned issue.
This MVP takes an approach such that the constraints listed below are
resolved;
- Have the intercept be specific to a single user
- Define a strategy to configure triggers that can vary for the
intercept that's not dependent on the client
How does this work?
- A generic plugin has been created which when declared as dependency
can be used to register and schedule an intercept that should be
presented to the user, this plugin is what's been used for the product
intercept dialog.
- To handle rendering the UI component that gets displayed to the users,
in this PR we hook into core's existing notification system, through the
notification coordinator system that's been created so that we don't
have a situation where an intercept is being displayed whilst a user
might have a toast being rendered to them, if there's an intercept to be
displayed said intercept would not be displayed till the user is
completely done interacting with the toast. [See it's implementation
details
here](src/core/packages/notifications/browser-internal/src/notification_coordinator.ts)
and
[here](x-pack/platform/plugins/private/intercepts/public/prompter/service/intercept_dialog_service.tsx)
for how it's integrated.
- The plugin provides some bootstrap data through an endpoint that every
user calls on page load, ideally this would need to happen just the once
on page load, we then compute when a user should see a trigger
leveraging the bootstrap data provided for the particular registered
trigger in question, the returned data returns the following data as
seen below;
<img width="476" alt="Screenshot 2025-03-27 at 18 01 12"
src="https://github.com/user-attachments/assets/c747b6c8-70d0-4305-b555-ec9998b180c1"
/>
Given we have this data we might then have a flow for triggering the
intercept on the client based of the bootstrap data like so;
```mermaid
flowchart TD
A[State Bootstrap] --> B{Has data?}
B -->|No| C(Do Nothing)
B -->|Yes| D{Does computed runs since trigger registration match stored
user trigger run feedback value?}
D -->|No| E[setup timer to display an intercept in that time]
E -->|on completion| G[setup interval to display intercept in the
future]
D -->|Yes| G
G -->|repeat| G
```
reloading the page restarts the entire process.
## Telemetry
The intercept component provided by defaults records telemetry for
intercept registration, acknowledgement (differentiated into dismissal
and completion), alongside registration overload.
## Visuals
<!--
https://github.com/user-attachments/assets/b39a506c-a119-40e8-9152-258d78691f28
-->
<!--
https://github.com/user-attachments/assets/f564b4bc-9ad9-4e19-8158-6e154ef52fc2
-->
<img width="738" alt="Screenshot 2025-05-07 at 19 41 23"
src="https://github.com/user-attachments/assets/902c6d0b-9299-44bd-8808-4ad97227d0da"
/>
## Testing this PR
- Pull this branch to your machine
- Add the following to your `kibana.dev.yml`, to enable the intercept to
run and be visible
```yml
xpack.intercepts.enabled: true
xpack.product_intercept.enabled: true
xpack.product_intercept.interval: '30s'
```
<!--
### Checklist
Check the PR satisfies following conditions.
Reviewers should verify this PR satisfies this list as well.
- [ ] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [ ] This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [ ] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
### Identify risks
Does this PR introduce any risks? For example, consider risks like hard
to test bugs, performance regression, potential of data loss.
Describe the risk, its severity, and mitigation for each identified
risk. Invite stakeholders and evaluate how to proceed before merging.
- [ ] [See some risk
examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)
- [ ] ...
-->
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
## Release Notes
Kibana logging's pattern layout, used by default for the console
appender, will now use a new default pattern layout
`[%date][%level][%logger] %message %error`. This will include the error
name and stack trace if these were included in the log entry. To opt out
of this behavior users can omit the `%error` placeholder from their log
pattern config in kibana.yml e.g.:
```
logging:
appenders:
console:
type: console
layout:
type: pattern
pattern: "[%date][%level][%logger] %message"
```
## Summary
Previously, when we pass the error in meta, the information related to
stacktrace and error message was not available in console. This PR
changed the default pattern to also include error information if it is
provided in meta (similar to the way that the logging happens when error
is directly passed to logger.error).
New pattern: (added `%error` at the end)
```
[%date][%level][%logger] %message %error
```
Here you can see the difference:
Logger:
```
server.logger.error(
`Unable to create Synthetics monitor ${monitorWithNamespace[ConfigKey.NAME]}`,
{ error: e }
);
```
#### Before

#### After

### Alternative
We could also change the MetaConversion and include this information,
but we might have additional meta information which I am not sure if it
is OK to be logged by default. Let me know if you prefer changing
MetaConversion instead of adding a new error conversion.
<details>
<summary>Code changes for MetaConversion</summary>
```
function isError(x: any): x is Error {
return x instanceof Error;
}
export const MetaConversion: Conversion = {
pattern: /%meta/g,
convert(record: LogRecord) {
if (!record.meta) {
return '';
}
const { error, ...rest } = record.meta;
const metaString = Object.keys(rest).length !== 0 ? JSON.stringify(rest) : '';
let errorString = '';
if (isError(record.meta?.error)) {
errorString = record.meta?.error.stack || '';
}
return [metaString, errorString].filter(Boolean).join(' ');
},
};
```
</details>
Here is how adjusting meta will look like in this case:

Behavioral analytics was hidden from the UI and its associated APIs were
deprecated in 9.0, but only the API deprecation was called out in
Elasticseach release notes. This PR addresses the UI communication gap
by adding a mention to the 9.0 breaking changes (while it's technically
a deprecation, the fact that it's been hidden in Kibana makes it look
more like a breaking change from a customer perspective).
Rel: https://github.com/elastic/docs-content/issues/1417
Rel: https://github.com/elastic/kibana/pull/212031
Updating release notes for 9.0.1 (docs V3) in main branch.
Not sure how we plan to deal with the security advisor messages in the
release notes in the new docs system, considering the release notes page
include a generic message at the beginning pointing to the security
advisory board.
Also I'm not totally sure if this needs to be merged into any other
branch, I'll let @wajihaparvez and @florent-leborgne to determine how
this should be done, and approve or reject the PR.
## Summary
Part of #218501
This PR removes the advanced setting
`observability:enableInfrastructureAssetCustomDashboards` but keeps the
saved object, to be removed in a [follow-up
issue](https://github.com/elastic/kibana/issues/220340).
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>