From 7d5b30f56e5053a04a2eb082be1ea8ed2cd0f2c8 Mon Sep 17 00:00:00 2001 From: Govinda Vashishtha <57435703+govindavashishtha@users.noreply.github.com> Date: Mon, 19 Oct 2026 18:04:13 +0530 Subject: [PATCH] fix(trueforge-ui): hide session share URL when access is Only you Stop offering a copyable share link for private sessions so people do not send inaccessible URLs (AGE-2534). Co-authored-by: Cursor --- .changeset/hide-only-you-session-share-url.md | 5 ++ .../src/atoms/ShareSessionDialog.tsx | 60 ++++++++++--------- .../test/atoms/SessionsPage.test.tsx | 13 +++- .../test/atoms/ShareChatButton.test.tsx | 19 ++++-- .../test/atoms/ShareSessionDialog.test.tsx | 42 ++++++++++++- 5 files changed, 104 insertions(+), 35 deletions(-) create mode 100644 .changeset/hide-only-you-session-share-url.md diff --git a/.changeset/hide-only-you-session-share-url.md b/.changeset/hide-only-you-session-share-url.md new file mode 100644 index 000000000..2014d108c --- /dev/null +++ b/.changeset/hide-only-you-session-share-url.md @@ -0,0 +1,5 @@ +--- +'@truefoundry/trueforge-ui': patch +--- + +Hide the session share URL when access is Only you. diff --git a/packages/trueforge-ui/src/atoms/ShareSessionDialog.tsx b/packages/trueforge-ui/src/atoms/ShareSessionDialog.tsx index 155ceb0c9..855d7ba00 100644 --- a/packages/trueforge-ui/src/atoms/ShareSessionDialog.tsx +++ b/packages/trueforge-ui/src/atoms/ShareSessionDialog.tsx @@ -129,34 +129,38 @@ export function ShareSessionDialog({ sessionId, trigger }: ShareSessionDialogPro void changePermission(next); }} /> -
-
- -

Share URL

-
-
- - { - track(AnalyticsEvents.Session.SHARE_LINK_COPIED, { - session_id: sessionId, - permission, - }); - copySharedSessionLink(); - }} - > - - {copied ? 'Copied' : 'Copy'} - -
+ {permission === 'tenant' ? ( + <> +
+
+ +

Share URL

+
+
+ + { + track(AnalyticsEvents.Session.SHARE_LINK_COPIED, { + session_id: sessionId, + permission, + }); + copySharedSessionLink(); + }} + > + + {copied ? 'Copied' : 'Copy'} + +
+ + ) : null} ); } diff --git a/packages/trueforge-ui/test/atoms/SessionsPage.test.tsx b/packages/trueforge-ui/test/atoms/SessionsPage.test.tsx index 78de15a5a..0adcba070 100644 --- a/packages/trueforge-ui/test/atoms/SessionsPage.test.tsx +++ b/packages/trueforge-ui/test/atoms/SessionsPage.test.tsx @@ -273,12 +273,21 @@ describe('SessionsPage', () => { it('copies the no-router shared-session query URL for the selected session', async () => { window.history.replaceState(null, '', '/?view=sessions&sessionId=sess-1&agentId=agent-1&s_tw=30'); - renderPage(); + renderPage({ + getSession: vi.fn(async (): Promise => ({ + id: 'sess-1', + title: 'Named session', + isMutable: false, + shared: true, + createdAt: namedRow.createdAt, + updatedAt: namedRow.updatedAt, + })), + }); fireEvent.click(await screen.findByRole('button', { name: 'Share' })); expect(await screen.findByText('Change permissions')).toBeInTheDocument(); expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); - fireEvent.click(screen.getByRole('button', { name: 'Copy' })); + fireEvent.click(await screen.findByRole('button', { name: 'Copy' })); await waitFor(() => { expect(clipboardWriteText).toHaveBeenCalledOnce(); diff --git a/packages/trueforge-ui/test/atoms/ShareChatButton.test.tsx b/packages/trueforge-ui/test/atoms/ShareChatButton.test.tsx index 25c13308a..97e00c6dd 100644 --- a/packages/trueforge-ui/test/atoms/ShareChatButton.test.tsx +++ b/packages/trueforge-ui/test/atoms/ShareChatButton.test.tsx @@ -52,11 +52,22 @@ describe('ShareChatButton', () => { it('opens the share popover and copies the routed shared-session URL', async () => { activeThread.remoteId = 'session-1'; + const server = createMockAgentUIServer({ + getSession: vi.fn(async () => ({ + id: 'session-1', + isMutable: true, + shared: true, + createdAt: '2026-01-01T00:00:00Z', + updatedAt: '2026-01-01T00:00:00Z', + })), + }); render( - - - + + + + + , ); @@ -64,7 +75,7 @@ describe('ShareChatButton', () => { expect(await screen.findByText('Change permissions')).toBeInTheDocument(); expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); - fireEvent.click(screen.getByRole('button', { name: 'Copy' })); + fireEvent.click(await screen.findByRole('button', { name: 'Copy' })); await waitFor(() => { expect(writeText).toHaveBeenCalledOnce(); }); diff --git a/packages/trueforge-ui/test/atoms/ShareSessionDialog.test.tsx b/packages/trueforge-ui/test/atoms/ShareSessionDialog.test.tsx index bb19e21e2..567d2ed62 100644 --- a/packages/trueforge-ui/test/atoms/ShareSessionDialog.test.tsx +++ b/packages/trueforge-ui/test/atoms/ShareSessionDialog.test.tsx @@ -85,11 +85,28 @@ async function openSharePopover() { } describe('ShareSessionDialog', () => { - it('loads current sharing and copies the share URL', async () => { + it('hides the share URL while access is Only you', async () => { renderDialog(); await openSharePopover(); expect(await screen.findByRole('button', { name: 'Session sharing' })).toHaveTextContent('Only you'); + expect(screen.queryByLabelText('Share URL')).not.toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'Copy' })).not.toBeInTheDocument(); + }); + + it('loads tenant sharing and copies the share URL', async () => { + renderDialog({ + getSession: vi.fn(async () => ({ + id: 'session-1', + isMutable: true, + shared: true, + createdAt: '2026-01-01T00:00:00Z', + updatedAt: '2026-01-01T00:00:00Z', + })), + }); + await openSharePopover(); + + expect(await screen.findByRole('button', { name: 'Session sharing' })).toHaveTextContent('Everyone within acme'); expect((screen.getByLabelText('Share URL') as HTMLInputElement).value).toContain('/sessions/share/session-1'); fireEvent.click(screen.getByRole('button', { name: 'Copy' })); @@ -100,6 +117,29 @@ describe('ShareSessionDialog', () => { expect(screen.getByRole('button', { name: 'Copied' })).toBeInTheDocument(); }); + it('shows the share URL after switching to tenant access and hides it again for Only you', async () => { + const { updateSession } = renderDialog(); + await openSharePopover(); + + expect(screen.queryByLabelText('Share URL')).not.toBeInTheDocument(); + + fireEvent.click(await screen.findByRole('button', { name: 'Session sharing' })); + fireEvent.click(await screen.findByRole('option', { name: 'Everyone within acme' })); + + await waitFor(() => { + expect(updateSession).toHaveBeenCalledWith({ sessionId: 'session-1', shared: true }); + }); + expect(screen.getByLabelText('Share URL')).toBeInTheDocument(); + + fireEvent.click(screen.getByRole('button', { name: 'Session sharing' })); + fireEvent.click(await screen.findByRole('option', { name: 'Only you' })); + + await waitFor(() => { + expect(updateSession).toHaveBeenCalledWith({ sessionId: 'session-1', shared: false }); + }); + expect(screen.queryByLabelText('Share URL')).not.toBeInTheDocument(); + }); + it('closes permission options on outside click without PATCHing', async () => { const { updateSession } = renderDialog(); await openSharePopover();