diff --git a/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/__tests__/sessions-sidebar.test.tsx b/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/__tests__/sessions-sidebar.test.tsx
index 1528564ec..09097c5a6 100644
--- a/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/__tests__/sessions-sidebar.test.tsx
+++ b/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/__tests__/sessions-sidebar.test.tsx
@@ -103,7 +103,7 @@ describe('SessionsSidebar', () => {
render();
expect(screen.getByText('Sessions')).toBeDefined();
expect(screen.getByText('Schedules')).toBeDefined();
- expect(screen.getByText('Sharing')).toBeDefined();
+ expect(screen.getByText('Pair Prompting')).toBeDefined();
expect(screen.getByText('Access Keys')).toBeDefined();
expect(screen.getByText('Workspace Settings')).toBeDefined();
});
diff --git a/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/sessions-sidebar.tsx b/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/sessions-sidebar.tsx
index ba40b4020..3d2dc2615 100644
--- a/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/sessions-sidebar.tsx
+++ b/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/sessions-sidebar.tsx
@@ -130,7 +130,7 @@ export function SessionsSidebar({
href: `/projects/${projectName}/scheduled-sessions`,
},
{
- label: "Sharing",
+ label: "Pair Prompting",
icon: Share2,
href: `/projects/${projectName}/permissions`,
},
diff --git a/components/frontend/src/components/workspace-sections/__tests__/sharing-section.test.tsx b/components/frontend/src/components/workspace-sections/__tests__/sharing-section.test.tsx
index 439bb52ec..71258d106 100644
--- a/components/frontend/src/components/workspace-sections/__tests__/sharing-section.test.tsx
+++ b/components/frontend/src/components/workspace-sections/__tests__/sharing-section.test.tsx
@@ -60,7 +60,7 @@ describe('SharingSection', () => {
it('renders permissions table with data', () => {
render();
- expect(screen.getByText('Sharing')).toBeDefined();
+ expect(screen.getByText('Pair Prompting')).toBeDefined();
expect(screen.getByText('developers')).toBeDefined();
expect(screen.getByText('alice')).toBeDefined();
});
@@ -87,7 +87,7 @@ describe('SharingSection', () => {
render();
fireEvent.click(screen.getByText('Grant Permission'));
- const nameInput = screen.getByPlaceholderText('Enter group name');
+ const nameInput = screen.getByPlaceholderText('e.g., platform-team');
fireEvent.change(nameInput, { target: { value: 'new-team' } });
// Click the Grant Permission button in the dialog footer
@@ -150,5 +150,6 @@ describe('SharingSection', () => {
render();
expect(screen.getByText('No users or groups have access yet')).toBeDefined();
+ expect(screen.queryByText('Grant First Permission')).toBeNull();
});
});
diff --git a/components/frontend/src/components/workspace-sections/sharing-section.tsx b/components/frontend/src/components/workspace-sections/sharing-section.tsx
index 642e73d61..4f7e4a997 100644
--- a/components/frontend/src/components/workspace-sections/sharing-section.tsx
+++ b/components/frontend/src/components/workspace-sections/sharing-section.tsx
@@ -1,7 +1,7 @@
'use client';
import { useCallback, useMemo, useState } from 'react';
-import { Users, User as UserIcon, Plus, Loader2, Trash2, Info } from 'lucide-react';
+import { Users, User as UserIcon, Plus, Loader2, Trash2, Info, HelpCircle } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
@@ -12,6 +12,7 @@ import { Label } from '@/components/ui/label';
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
+import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { DestructiveConfirmationDialog } from '@/components/confirmation-dialog';
import { useProjectPermissions, useAddProjectPermission, useRemoveProjectPermission } from '@/services/queries';
@@ -50,6 +51,8 @@ export function SharingSection({ projectName }: SharingSectionProps) {
const isAdmin = userRole === 'admin' || userRole === undefined;
+ const subjectPlaceholder = grantForm.subjectType === 'group' ? 'e.g., platform-team' : 'e.g., jdoe@example.com';
+
const handleGrant = useCallback(() => {
if (!grantForm.subjectName.trim()) {
setGrantError(`${grantForm.subjectType === 'group' ? 'Group' : 'User'} name is required`);
@@ -113,16 +116,10 @@ export function SharingSection({ projectName }: SharingSectionProps) {
() => (
-
No users or groups have access yet
- {isAdmin && (
-
- )}
+
No users or groups have access yet
),
- [isAdmin]
+ []
);
return (
@@ -143,7 +140,7 @@ export function SharingSection({ projectName }: SharingSectionProps) {
- Sharing
+ Pair Prompting
Users and groups with access to this workspace and their roles
@@ -227,9 +224,9 @@ export function SharingSection({ projectName }: SharingSectionProps) {
- {/* Grant Permission Dialog */}
-
+
+
+
+
+
+
+
+ {grantForm.subjectType === 'group' ? (
+ Enter the LDAP or identity provider group name, e.g. platform-team, ai-engineering
+ ) : (
+ Enter the username or email, e.g. jdoe, jdoe@example.com
+ )}
+
+
+
{ldapEnabled ? (
setGrantForm((prev) => ({ ...prev, subjectName: val }))}
disabled={addPermissionMutation.isPending}
@@ -266,7 +277,7 @@ export function SharingSection({ projectName }: SharingSectionProps) {
) : (
setGrantForm((prev) => ({ ...prev, subjectName: e.target.value }))}
disabled={addPermissionMutation.isPending}
@@ -327,10 +338,10 @@ export function SharingSection({ projectName }: SharingSectionProps) {
)}
+
- {/* Revoke Permission Dialog */}
{
it('should visit each workspace page via direct routes', () => {
// Each workspace section now has its own route (no more ?section= params)
- // Sharing page — covers sharing-section.tsx
+ // Pair Prompting page — covers sharing-section.tsx
cy.visit(`/projects/${workspaceSlug}/permissions`)
- cy.get('body', { timeout: 10000 }).should('contain.text', 'Sharing')
+ cy.get('body', { timeout: 10000 }).should('contain.text', 'Pair Prompting')
cy.wait(500)
// Access Keys page — covers keys page
@@ -484,7 +484,7 @@ describe('Ambient Session Management Tests', () => {
it('should interact with sharing tab', () => {
cy.visit(`/projects/${workspaceSlug}/permissions`)
- cy.get('body', { timeout: 15000 }).should('contain.text', 'Sharing')
+ cy.get('body', { timeout: 15000 }).should('contain.text', 'Pair Prompting')
// Look for "Grant Permission" button
cy.get('body').then(($body) => {
@@ -1339,11 +1339,11 @@ describe('Ambient Session Management Tests', () => {
it('should interact with sharing tab Grant Permission dialog', () => {
cy.visit(`/projects/${workspaceSlug}/permissions`)
- cy.get('body', { timeout: 15000 }).should('contain.text', 'Sharing')
+ cy.get('body', { timeout: 15000 }).should('contain.text', 'Pair Prompting')
- // Look for "Grant Permission" or "Grant First Permission" button
+ // Look for "Grant Permission" button
cy.get('body').then(($body) => {
- const grantBtn = $body.find('button:contains("Grant Permission"), button:contains("Grant First Permission")')
+ const grantBtn = $body.find('button:contains("Grant Permission")')
if (grantBtn.length) {
cy.wrap(grantBtn.first()).click({ force: true })
cy.wait(500)
@@ -1654,7 +1654,7 @@ describe('Ambient Session Management Tests', () => {
it('should click Refresh button on sharing tab', () => {
cy.visit(`/projects/${workspaceSlug}/permissions`)
- cy.get('body', { timeout: 15000 }).should('contain.text', 'Sharing')
+ cy.get('body', { timeout: 15000 }).should('contain.text', 'Pair Prompting')
cy.get('body').then(($body) => {
if ($body.find('button:contains("Refresh")').length) {