import { expect, test, type Page } from '@playwright/test'; import { login as loginAs, logout } from './helpers'; // Permission boundary in the browser, against the restricted corpus // document "Wissenssicherung: Werner Krause" (visibility: restricted, // granted to Engineering only). Pablo (Engineering) sees it, Max (Sales) // must not — in the list, in the detail view, and in chat sources. test.setTimeout(120_000); async function login(page: Page, email: string) { await loginAs(page, email); } test('restricted corpus document stays invisible across list, detail and chat', async ({ page }) => { // Pablo (Engineering, has the grant) can see it — and we grab the id. await login(page, 'pablo@pablan.dev'); const fromApi = (await (await page.request.get('/api/documents?search=Wissenssicherung')).json()) .items; expect(fromApi.length).toBeGreaterThan(0); const restrictedId = fromApi[0].id; await page.goto('/documents'); await page.locator('body[data-hydrated]').waitFor(); await page.getByTestId('document-search').fill('Wissenssicherung'); await expect(page.getByTestId('document-list')).toContainText('Wissenssicherung: Werner Krause', { timeout: 10_000 }); await logout(page); // Max (Sales): list is empty, detail 404s, chat cites nothing restricted. await login(page, 'max@pablan.dev'); await page.goto('/documents'); await page.locator('body[data-hydrated]').waitFor(); await page.getByTestId('document-search').fill('Wissenssicherung Werner Krause'); // Search ranks by meaning, so it returns related documents rather than // nothing — what matters is that the restricted one is never among them. await expect( page.getByTestId('document-list').or(page.getByText('No documents match')) ).toBeVisible({ timeout: 15_000 }); await expect(page.locator('body')).not.toContainText('Wissenssicherung: Werner Krause'); await page.goto(`/documents/${restrictedId}`); await expect(page.getByText('Document not found')).toBeVisible(); await page.getByTestId('sidebar-new-conversation').click(); await page .getByTestId('chat-input') .fill('Welcher Servotec-Techniker kennt die F-350 am besten?'); await page.getByTestId('send-button').click(); await expect(page.getByTestId('send-button')).toBeVisible({ timeout: 60_000 }); const sources = page.getByTestId('sources'); if ((await sources.count()) > 0) { await expect(sources.last()).not.toContainText('Wissenssicherung'); } // Cleanup: ben's chat question created a conversation; drop it + session. const conversations = await (await page.request.get('/api/conversations')).json(); if (conversations.length > 0) { await page.request.delete(`/api/conversations/${conversations[0].id}`); } await page.request.post('/api/auth/logout'); });