From a777aeac45ba273576835ccec3c4c71c8c40e0ff Mon Sep 17 00:00:00 2001 From: arc53-machine <232052973+arc53-machine@users.noreply.github.com> Date: Tue, 29 Sep 2026 14:12:35 +0100 Subject: [PATCH] Open a team's shared source on the Knowledge page Also cover the owner-only API write allowlist in the agent details modal. --- .../src/modals/AgentDetailsModal.test.tsx | 34 +++++++++++++++++-- frontend/src/settings/Teams.test.tsx | 28 ++++++++++++++- frontend/src/settings/Teams.tsx | 2 +- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/frontend/src/modals/AgentDetailsModal.test.tsx b/frontend/src/modals/AgentDetailsModal.test.tsx index 1f3ccc26..603e9800 100644 --- a/frontend/src/modals/AgentDetailsModal.test.tsx +++ b/frontend/src/modals/AgentDetailsModal.test.tsx @@ -17,8 +17,11 @@ vi.mock('react-redux', () => ({ })); vi.mock('../api/services/userService', () => ({ default: mocks })); -// Tested on its own; it needs the store and the tool list. -vi.mock('../agents/ApiWriteAllowlist', () => ({ default: () => null })); +// Tested on its own; it needs the store and the tool list. Here it only has +// to show up (or not). +vi.mock('../agents/ApiWriteAllowlist', () => ({ + default: () =>
, +})); vi.mock('./ConfirmationModal', () => ({ default: ({ @@ -99,6 +102,33 @@ describe('AgentDetailsModal', () => { ); }); + // The allowlist acts on the owner's connected accounts; the server keeps + // it unchanged for anyone else, so only the owner sees it. + describe('API write allowlist', () => { + const allowlist = () => + document.querySelector('[data-testid="api-write-allowlist"]'); + + it('shows it to the owner of an agent with a key', async () => { + await render({ status: 'published', key: 'k-1', access: 'owner' }); + expect(allowlist()).not.toBeNull(); + }); + + it('hides it from an editor, even with a key', async () => { + await render({ + status: 'published', + key: 'k-1', + access: 'editor', + allowed_actions: ['view', 'edit', 'manage_access_details'], + }); + expect(allowlist()).toBeNull(); + }); + + it('hides it until the agent has a key', async () => { + await render({ status: 'published', access: 'owner' }); + expect(allowlist()).toBeNull(); + }); + }); + it('shows a refused public link in an alert', async () => { mocks.shareAgent.mockReturnValue( respond({ success: false, message: 'Not allowed' }, false), diff --git a/frontend/src/settings/Teams.test.tsx b/frontend/src/settings/Teams.test.tsx index 218403a7..e64b5214 100644 --- a/frontend/src/settings/Teams.test.tsx +++ b/frontend/src/settings/Teams.test.tsx @@ -1,6 +1,6 @@ import { act } from 'react'; import { createRoot, type Root } from 'react-dom/client'; -import { MemoryRouter } from 'react-router-dom'; +import { MemoryRouter, useLocation } from 'react-router-dom'; // A JWT whose payload is {"sub":"me"}. const TOKEN = `x.${btoa(JSON.stringify({ sub: 'me' }))}.y`; @@ -183,6 +183,10 @@ describe('Teams page', () => { document.body.innerHTML = ''; }); + function Where() { + return