[Security Assistant] Conversation sharing#230614
[Security Assistant] Conversation sharing#230614stephmilovic merged 153 commits intoelastic:mainfrom
Conversation
|
Still need to test Telemetry and Audit logging. |
| /** | ||
| * The full name of the user. | ||
| */ | ||
| full_name: z.string().optional(), |
There was a problem hiding this comment.
Not particularly related to your changes, but I see we are mixing camel and snake case styles in assistant APIs. Wondering whether we should try to stick to one of them.
| createdBy: { id: 'userX', name: 'Alice' }, | ||
| users: [user, otherUser], | ||
| }; | ||
| expect(getIsConversationOwner(conversation, user)).toBe(true); |
There was a problem hiding this comment.
Just to double check, is the name same as a username?
| import type { ConversationResponse, User } from '../schemas'; | ||
|
|
||
| export const getCurrentConversationOwner = ( | ||
| conversation?: Pick<ConversationResponse, 'createdBy' | 'users'> |
There was a problem hiding this comment.
Is there any reason to make conversation optional?
There was a problem hiding this comment.
its optional in the assistant, so it may be undefined if passed to this function
| */ | ||
| export const getIsConversationOwner = ( | ||
| // keep type loose for use in both assistant package and security plugins | ||
| conversation: Pick<ConversationResponse, 'createdBy' | 'users' | 'id'> | undefined, |
There was a problem hiding this comment.
Same here, is there a reason to allow undefined conversation?
There was a problem hiding this comment.
its optional in the assistant, so it may be undefined if passed to this function
| id: user?.uid ?? '', | ||
| name: user?.user?.username ?? '', | ||
| })), | ||
| // readd current user |
There was a problem hiding this comment.
| // readd current user | |
| // read current user |
There was a problem hiding this comment.
re-add, not read
x-pack/solutions/security/plugins/elastic_assistant/server/routes/register_routes.ts
Show resolved
Hide resolved
e40pud
left a comment
There was a problem hiding this comment.
Thanks for the new feature @stephmilovic!! Code changes LGTM ❤️
Thanks @KDKHD for the local testing! 🚀
Just a note, there are changes coming from my side relevant to the "conversation summary" which might be in conflict with this PR. I'm still waiting for the docs team to add dependencies for the AI Assistant before I can merge those.
could not reproduce
This is happening in other user selects too (cases, alerts). I think it is an issue with the
Fixed here: 1674cf9
This one is interesting, happening only some of the times to me. I'll investigate further |
…r/ai_assistant_data_clients/conversations/transform.test.ts`
💚 Build Succeeded
Metrics [docs]Module Count
Public APIs missing comments
Async chunks
Public APIs missing exports
Page load bundle
Unknown metric groupsAPI count
ESLint disabled line counts
Total ESLint disabled count
History
|
|
Friendly reminder: Looks like this PR hasn’t been backported yet. |
Fixes #2815 by documenting chat sharing for AI Assistant. Related Kibana PR: elastic/kibana#230614 --------- Co-authored-by: Mike Birnstiehl <114418652+mdbirnstiehl@users.noreply.github.com> Co-authored-by: Steph Milovic <stephanie.milovic@elastic.co> Co-authored-by: Dhrumil Patel <96066689+dhru42@users.noreply.github.com> Co-authored-by: natasha-moore-elastic <137783811+natasha-moore-elastic@users.noreply.github.com>

Summary
Adds conversation sharing functionality to the Security Assistant, allowing users to share conversations with team members. The implementation includes ownership tracking, sharing controls, and appropriate access restrictions for shared conversations.
suggestinternal endpoint to search users as required by user profile serviceAPI changes
New fields on conversation
createdByis now a required field on conversations.messages[0].useris now included when the message hasrole === 'user'.usersarray can now be updated when modifying a conversation:usersarray indicates a shared conversation.usersarray with one entry indicates a private conversation.usersarray with multiple entries indicates a restricted conversation.Note on legacy conversations:
Older conversations do not include the new
createdByfield. Instead, they follow the previous convention where theusersarray contains a single entry for the conversation owner.There is no migration step. Instead, when a legacy conversation is updated:
createdByfield is backfilled using the value fromusers[0].role=usermessage is assigned auservalue during the update.This logic is applied in the
painlessupdate script.Because of this, permission checks are required on both the client and server:
getCurrentConversationOwnerandgetIsConversationOwner, handle owner resolution by checkingcreatedByfirst, then falling back tousers[0].getIsConversationOwnerprevents users from updating conversations they do not own.getCurrentConversationOwneris used to determine the user avatar when arole=usermessage does not already specify auser.Find conversation route updates
The find conversation route now supports a new query parameter,
is_owner(default:false).is_owner: falseReturns private conversations the user owns, restricted conversations shared with them, and globally shared conversations:
is_owner: trueReturns only conversations owned by the user::
Documents data writer
The
getFilterByUserquery was updated to restrict updates to conversations unless owned by the current user, consistent with the owned-conversation KQL.Telemetry
The following server telemetry event types have been added:
conversation_shared_successconversation_shared_errorshared_conversation_accessed- when a non-owner accesses a conversationconversation_duplicatedAudit logging
The following audit logging been added:
security_assistant_conversation_sharedsecurity_assistant_conversation_privatesecurity_assistant_conversation_restrictedUI Changes
Share badge
When the user interacts with the new Share badge, there will be 3 selections: Private, Shared, and Restricted. When the conversation owner changes to Private or Shared, a success toast should appear. If a conversation owner changes to Restricted, a Share Modal opens and allows the user to select specific team members to share the conversation with.
Share modal
Share icons
When Shared is selected, a



usersicon should appear on the share badge and in the Conversation list item. When Restricted is selected, the Share Icon will bereadOnly. The private conversation icon is alock. If the conversation was owner shared, the Share Icon in the Conversation list item will be pink (changing before release). If the conversation was shared with the user, the Share Icon will be text color.Owner shared callout
When a conversation has been shared and the current user is the owner, they will see the Owner shared callout. The callout informs the user that the conversation is shared and any further edits/messages will also be shared. It can be dismissed per conversation, the dismissal status is stored in local storage. The Owner shared callout will also have the appropriate Share Icon.

Conversation list items
We already covered that the Conversation list items now have a Share icon indicating the conversation's shared status. The Conversation list items were also updated to include a context menu, with options to Copy URL, Duplicate, and if conversation owner, Delete. We'll cover the new actions in a bit.


Conversation settings menu
The assistant's context settings menu has split into two menus, a Conversation settings menu and an Assistant settings menu. As their titles indicate, the category of actions depends on which menu. The assistant setting actions will be the same regardless of ownership. The conversation settings actions will depend on conversation ownership, much like the conversation list items.



Responsive assistant header
Due to the addition of the Share Badge and the Conversation Settings Menu, I needed to make adjustments for the header to be responsive.
Screen.Recording.2025-08-26.at.3.19.01.PM.mov
Shared Conversation Callout
When a conversation has been shared with you, you will be unable to make edits to the conversation or send any new messages in the conversation. The original owner could continue the conversation and you will see their new messages appear. The Shared Conversation Callout informs the user of the functionality, and suggests they duplicate the conversation (see below) if they want to continue. Like the Owner shared callout, this callout can also be dismissed and the dismissal state is tracked per conversation id in local storage.

Copy URL action
As mentioned earlier, we now support a Copy URL action. This is currently the only way to inform a user of a message shared with them. The message owner must send them a URL to open it directly, or they may discover it themselves in their conversation list. The url copied always links to the getting started page to ensure there are not access issue. However, any url within security that has the query parameter
?assistant=12345will open the assistant with the conversation selected. If you do not have access to the conversation, the assistant will open to a new conversation just as if you had tried to open a deleted conversation from local storage. We can iterate later on someconversation not shared with youmessaging. There are Copy URL buttons in the Share Modal, Conversation List Items, and Conversation Settings Menu.Duplicate conversation action
Any conversation can now be duplicated from the Shared Conversation Callout, Conversation List Items, and Conversation Settings Menu. It will be titled
[Duplicate] Original titleand the user will become the owner of this new conversation. The usefulness of this feature comes when someone has shared a conversation with you and you can duplicate the conversation to continue the conversation.Screen.Recording.2025-08-26.at.3.20.12.PM.mov
Conversation settings
The final area with UI changes is the Conversation settings page. This page only shows user owned conversation. A new column has been added to the table with the share badge. Additionally, the edit flyout has a Share select where the conversation share state can be updated.


Testing Instructions
The sharing feature is behind a feature flag. Enable it by adding:
In
kibana.dev.yml, enable audit logging and telemetry for testing:Setup
-E xpack.security.audit.enabledcreated_atmapping does not exist yet.Verification Steps
User isolation
Repeat with User B.
Sharing from User A
While logged in as User A:
Verify with User A:
Viewing as User B
Duplicate the conversation:
New messages are attributed to User B.
Dismiss the Shared Conversation Callout on a shared conversation, switch to another, then return. Confirm the dismissal persists.
Conversation list
Open the conversation list in the Assistant sidebar:
Share User B’s conversations globally and with specific users. Confirm icons display correctly.
Copy URL
Conversation menus
Role restrictions
From User A or User B, try assigning a conversation to Bad User.
Telemetry
Audit logging
logs/directory in root for the audit log actions (security_assistant_conversation_shared,security_assistant_conversation_restricted, andsecurity_assistant_conversation_private)