@invect/rbac 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +39 -77
  2. package/dist/backend/index.cjs +72 -40
  3. package/dist/backend/index.cjs.map +1 -1
  4. package/dist/backend/index.d.cts +49 -0
  5. package/dist/backend/index.d.cts.map +1 -0
  6. package/dist/backend/index.d.mts +49 -0
  7. package/dist/backend/index.d.mts.map +1 -0
  8. package/dist/backend/index.d.ts +1 -1
  9. package/dist/backend/index.d.ts.map +1 -1
  10. package/dist/backend/index.mjs +72 -40
  11. package/dist/backend/index.mjs.map +1 -1
  12. package/dist/backend/plugin.d.ts +12 -14
  13. package/dist/backend/plugin.d.ts.map +1 -1
  14. package/dist/frontend/components/TeamsPage.d.ts.map +1 -1
  15. package/dist/frontend/components/access-control/ScopeDetailPanel.d.ts.map +1 -1
  16. package/dist/frontend/components/access-control/index.d.ts +0 -1
  17. package/dist/frontend/components/access-control/index.d.ts.map +1 -1
  18. package/dist/frontend/index.cjs +61 -61
  19. package/dist/frontend/index.cjs.map +1 -1
  20. package/dist/frontend/index.d.cts +227 -0
  21. package/dist/frontend/index.d.cts.map +1 -0
  22. package/dist/frontend/index.d.mts +227 -0
  23. package/dist/frontend/index.d.mts.map +1 -0
  24. package/dist/frontend/index.d.ts +2 -2
  25. package/dist/frontend/index.d.ts.map +1 -1
  26. package/dist/frontend/index.mjs +7 -7
  27. package/dist/frontend/index.mjs.map +1 -1
  28. package/dist/frontend/types.d.ts +1 -1
  29. package/dist/shared/types.d.cts +2 -0
  30. package/dist/shared/types.d.mts +2 -0
  31. package/dist/types-D4DI2gyU.d.cts +175 -0
  32. package/dist/types-D4DI2gyU.d.cts.map +1 -0
  33. package/dist/types-DxJoguYy.d.mts +175 -0
  34. package/dist/types-DxJoguYy.d.mts.map +1 -0
  35. package/package.json +44 -46
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["X","ChevronDown","Share2","Share2","Shield","Users","User","useUsers","DropdownMenu","DropdownMenuTrigger","ChevronDown","DropdownMenuContent","DropdownMenuLabel","DropdownMenuSeparator","DropdownMenuItem","Fragment","User","Users","Trash2","Dialog","DialogContent","DialogHeader","DialogTitle","DialogFooter","Dialog","DialogContent","DialogHeader","DialogTitle","User","X","Users","Trash2","ChevronRight","Plus","Dialog","DialogContent","DialogHeader","DialogTitle","DialogFooter","User","Users","X","Workflow","ChevronRight","ExternalLink","Plus","Move","X","User","Users","findScopeNode","Workflow","GripVertical","ChevronDown","ChevronRight","Users","useUsers","PageLayout","Shield","Search","Plus","FolderInput","PageLayout","Users","Plus","Search","ChevronDown","ChevronRight","Trash2","User","X","Shield"],"sources":["../../src/frontend/providers/RbacProvider.tsx","../../src/frontend/hooks/useFlowAccess.ts","../../src/frontend/components/ShareFlowModal.tsx","../../src/frontend/components/ShareButton.tsx","../../src/frontend/components/FlowAccessPanel.tsx","../../src/frontend/hooks/useTeams.ts","../../src/frontend/hooks/useScopes.ts","../../src/frontend/components/access-control/types.ts","../../src/frontend/components/access-control/useUsers.ts","../../src/frontend/components/access-control/AccessTable.tsx","../../src/frontend/components/access-control/FormDialog.tsx","../../src/frontend/components/access-control/MemberCombobox.tsx","../../src/frontend/components/access-control/ScopeDetailPanel.tsx","../../src/frontend/components/access-control/PrincipalCombobox.tsx","../../src/frontend/components/access-control/FlowDetailPanel.tsx","../../src/frontend/components/access-control/MoveConfirmationDialog.tsx","../../src/frontend/stores/accessControlStore.ts","../../src/frontend/components/access-control/AccessControlPage.tsx","../../src/frontend/components/TeamsPage.tsx","../../src/frontend/components/UserMenuSection.tsx","../../src/frontend/index.ts"],"sourcesContent":["/**\n * RBAC Context Provider\n *\n * Wraps the Invect app tree with RBAC state — current user identity,\n * permissions cache, and permission-checking utilities.\n *\n * Fetches GET /plugins/auth/me on mount and caches the result.\n */\n\nimport { createContext, useContext, useCallback, useMemo, type ReactNode } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { useApiClient } from '@invect/frontend';\nimport type { AuthMeResponse } from '../../shared/types';\n\n// ─────────────────────────────────────────────────────────────\n// Context Types\n// ─────────────────────────────────────────────────────────────\n\nexport interface RbacContextValue {\n /** Current user identity, null if not authenticated */\n user: AuthMeResponse['identity'];\n /** Whether the user is authenticated */\n isAuthenticated: boolean;\n /** Set of all permissions the user has */\n permissions: Set<string>;\n /** Check if the user has a specific permission */\n checkPermission: (permission: string) => boolean;\n /** Whether the auth/me query is still loading */\n isLoading: boolean;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Context\n// ─────────────────────────────────────────────────────────────\n\nconst RbacContext = createContext<RbacContextValue | null>(null);\n\n// ─────────────────────────────────────────────────────────────\n// Provider\n// ─────────────────────────────────────────────────────────────\n\nexport function RbacProvider({ children }: { children: ReactNode }) {\n const api = useApiClient();\n\n const { data: me, isLoading } = useQuery<AuthMeResponse>({\n queryKey: ['rbac', 'auth', 'me'],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/auth/me`, {\n credentials: 'include',\n });\n if (!response.ok) {\n // If auth endpoint doesn't exist or fails, return unauthenticated\n return {\n identity: null,\n permissions: [],\n isAuthenticated: false,\n };\n }\n return response.json();\n },\n staleTime: 5 * 60 * 1000, // 5 minutes\n retry: 1,\n });\n\n const permissions = useMemo(() => new Set(me?.permissions ?? []), [me?.permissions]);\n\n const checkPermission = useCallback(\n (permission: string): boolean => {\n if (!me?.isAuthenticated) {\n return true; // No auth = allow all (matches core default)\n }\n return permissions.has(permission) || permissions.has('admin:*');\n },\n [me?.isAuthenticated, permissions],\n );\n\n const value = useMemo<RbacContextValue>(\n () => ({\n user: me?.identity ?? null,\n isAuthenticated: me?.isAuthenticated ?? false,\n permissions,\n checkPermission,\n isLoading,\n }),\n [me, permissions, checkPermission, isLoading],\n );\n\n return <RbacContext.Provider value={value}>{children}</RbacContext.Provider>;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Hook\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Access RBAC context — current user, permissions, and permission checking.\n *\n * Must be used within an `<RbacProvider>`.\n * Returns a safe fallback (unauthenticated, allow all) if provider is missing.\n */\nexport function useRbac(): RbacContextValue {\n const ctx = useContext(RbacContext);\n\n if (!ctx) {\n // Graceful fallback — allow everything if RBAC provider isn't mounted\n return {\n user: null,\n isAuthenticated: false,\n permissions: new Set(),\n checkPermission: () => true,\n isLoading: false,\n };\n }\n\n return ctx;\n}\n","/**\n * useFlowAccess — React Query hooks for flow access records\n */\n\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { useApiClient } from '@invect/frontend';\nimport type {\n AccessibleFlowsResponse,\n FlowAccessRecord,\n GrantFlowAccessRequest,\n} from '../../shared/types';\n\n/** Fetch access records for a specific flow */\nexport function useFlowAccess(flowId: string | undefined) {\n const api = useApiClient();\n\n return useQuery<{ access: FlowAccessRecord[] }>({\n queryKey: ['rbac', 'flow-access', flowId],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/flows/${flowId}/access`, {\n credentials: 'include',\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch flow access: ${response.status}`);\n }\n return response.json();\n },\n enabled: !!flowId,\n });\n}\n\n/** Fetch all flow IDs accessible to the current user with their effective permission */\nexport function useAccessibleFlows() {\n const api = useApiClient();\n\n return useQuery<AccessibleFlowsResponse>({\n queryKey: ['rbac', 'accessible-flows'],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/flows/accessible`, {\n credentials: 'include',\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(\n err.error || err.message || `Failed to fetch accessible flows: ${response.status}`,\n );\n }\n return response.json();\n },\n });\n}\n\n/** Grant access to a flow */\nexport function useGrantFlowAccess(flowId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (input: GrantFlowAccessRequest) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/flows/${flowId}/access`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n },\n credentials: 'include',\n body: JSON.stringify(input),\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to grant access: ${response.status}`);\n }\n return response.json();\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'flow-access', flowId] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'effective-flow-access', flowId] });\n },\n });\n}\n\n/** Revoke a specific access record */\nexport function useRevokeFlowAccess(flowId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (accessId: string) => {\n const response = await fetch(\n `${api.getBaseURL()}/plugins/rbac/flows/${flowId}/access/${accessId}`,\n {\n method: 'DELETE',\n credentials: 'include',\n },\n );\n if (!response.ok && response.status !== 204) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to revoke access: ${response.status}`);\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'flow-access', flowId] });\n },\n });\n}\n","/**\n * ShareFlowModal — Modal for managing flow access permissions.\n *\n * Shows current access records and allows granting/revoking access.\n */\n\nimport { useState } from 'react';\nimport { ChevronDown, Share2, X } from 'lucide-react';\nimport { useFlowAccess, useGrantFlowAccess, useRevokeFlowAccess } from '../hooks/useFlowAccess';\nimport { useRbac } from '../providers/RbacProvider';\nimport type { FlowAccessPermission } from '../../shared/types';\n\nconst AVATAR_COLORS = [\n 'bg-blue-500/15 text-blue-600 dark:text-blue-400',\n 'bg-violet-500/15 text-violet-600 dark:text-violet-400',\n 'bg-emerald-500/15 text-emerald-600 dark:text-emerald-400',\n 'bg-amber-500/15 text-amber-600 dark:text-amber-400',\n 'bg-rose-500/15 text-rose-600 dark:text-rose-400',\n 'bg-cyan-500/15 text-cyan-600 dark:text-cyan-400',\n 'bg-fuchsia-500/15 text-fuchsia-600 dark:text-fuchsia-400',\n 'bg-orange-500/15 text-orange-600 dark:text-orange-400',\n];\n\nfunction getAvatarColor(id: string): string {\n let hash = 0;\n for (let i = 0; i < id.length; i++) {\n hash = ((hash << 5) - hash + id.charCodeAt(i)) | 0;\n }\n return AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length];\n}\n\nfunction getPermissionColor(permission: FlowAccessPermission): string {\n switch (permission) {\n case 'owner':\n return 'border-amber-500/30 bg-amber-500/5 text-amber-600 dark:text-amber-400';\n case 'editor':\n return 'border-blue-500/30 bg-blue-500/5 text-blue-600 dark:text-blue-400';\n case 'operator':\n return 'border-emerald-500/30 bg-emerald-500/5 text-emerald-600 dark:text-emerald-400';\n case 'viewer':\n default:\n return 'border-imp-border bg-imp-muted/50 text-imp-muted-foreground';\n }\n}\n\nconst PERMISSION_OPTIONS: Array<{ value: FlowAccessPermission; label: string }> = [\n { value: 'viewer', label: 'Viewer' },\n { value: 'operator', label: 'Operator' },\n { value: 'editor', label: 'Editor' },\n { value: 'owner', label: 'Owner' },\n];\n\n// ─────────────────────────────────────────────────────────────\n// Component\n// ─────────────────────────────────────────────────────────────\n\ninterface ShareFlowModalProps {\n flowId: string;\n onClose: () => void;\n}\n\nexport function ShareFlowModal({ flowId, onClose }: ShareFlowModalProps) {\n const { user } = useRbac();\n const { data, isLoading } = useFlowAccess(flowId);\n const grantAccess = useGrantFlowAccess(flowId);\n const revokeAccess = useRevokeFlowAccess(flowId);\n\n const [newPrincipal, setNewPrincipal] = useState('');\n const [newPermission, setNewPermission] = useState<FlowAccessPermission>('viewer');\n const [principalType, setPrincipalType] = useState<'user' | 'team'>('user');\n const [error, setError] = useState<string | null>(null);\n const [openRoleDropdown, setOpenRoleDropdown] = useState<string | null>(null);\n\n const accessRecords = data?.access ?? [];\n\n const handleGrant = async () => {\n if (!newPrincipal.trim()) {\n setError('Please enter a user ID or team ID');\n return;\n }\n\n setError(null);\n try {\n await grantAccess.mutateAsync({\n ...(principalType === 'user' ? { userId: newPrincipal } : { teamId: newPrincipal }),\n permission: newPermission,\n });\n setNewPrincipal('');\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to grant access');\n }\n };\n\n const handleRevoke = async (accessId: string) => {\n try {\n await revokeAccess.mutateAsync(accessId);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to revoke access');\n }\n };\n\n const handleChangeRole = async (\n accessId: string,\n record: (typeof accessRecords)[0],\n newRole: FlowAccessPermission,\n ) => {\n try {\n await grantAccess.mutateAsync({\n ...(record.userId\n ? { userId: record.userId }\n : record.teamId\n ? { teamId: record.teamId }\n : {}),\n permission: newRole,\n });\n setOpenRoleDropdown(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to update role');\n }\n };\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\"\n onClick={onClose}\n >\n <div\n className=\"w-full max-w-md rounded-xl border border-imp-border bg-imp-background p-5 shadow-2xl\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-base font-semibold text-imp-foreground\">Share Flow</h2>\n <button\n onClick={onClose}\n className=\"rounded-lg p-1.5 text-imp-muted-foreground transition-colors hover:bg-imp-muted hover:text-imp-foreground\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n\n {/* Error */}\n {error && (\n <div className=\"mb-3 rounded-lg bg-red-50 px-3 py-2 text-sm text-red-600 dark:bg-red-950/20 dark:text-red-400\">\n {error}\n </div>\n )}\n\n {/* Current access records */}\n <div className=\"mb-4\">\n <h3 className=\"mb-2 text-xs font-medium uppercase tracking-wide text-imp-muted-foreground\">\n People with access\n </h3>\n {isLoading ? (\n <div className=\"py-4 text-center text-sm text-imp-muted-foreground\">Loading...</div>\n ) : accessRecords.length === 0 ? (\n <div className=\"py-4 text-center text-sm text-imp-muted-foreground\">\n No flow-specific access records yet.\n </div>\n ) : (\n <div className=\"max-h-48 space-y-0.5 overflow-y-auto\">\n {accessRecords.map((record) => {\n const principalId = record.userId ?? record.teamId ?? '?';\n const isCurrentUser = record.userId === user?.id;\n const isRoleDropdownOpen = openRoleDropdown === record.id;\n\n return (\n <div\n key={record.id}\n className=\"flex items-center justify-between rounded-lg px-2.5 py-2 transition-colors hover:bg-imp-muted/30\"\n >\n <div className=\"flex items-center gap-2.5 min-w-0\">\n <div\n className={`flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-xs font-semibold ${getAvatarColor(principalId)}`}\n >\n {principalId[0]?.toUpperCase()}\n </div>\n <span className=\"truncate text-sm font-medium text-imp-foreground\">\n {principalId}\n {isCurrentUser && (\n <span className=\"ml-1 font-normal text-imp-muted-foreground\">(you)</span>\n )}\n </span>\n </div>\n <div className=\"relative\">\n {isCurrentUser ? (\n <span\n className={`inline-flex rounded-full border px-2.5 py-0.5 text-xs font-medium capitalize ${getPermissionColor(record.permission)}`}\n >\n {record.permission}\n </span>\n ) : (\n <>\n <button\n type=\"button\"\n onClick={() =>\n setOpenRoleDropdown(isRoleDropdownOpen ? null : record.id)\n }\n className={`inline-flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-xs font-medium capitalize transition-colors hover:bg-imp-muted/50 ${getPermissionColor(record.permission)}`}\n >\n {record.permission}\n <ChevronDown className=\"h-3 w-3\" />\n </button>\n {isRoleDropdownOpen && (\n <>\n <div\n className=\"fixed inset-0 z-10\"\n onClick={() => setOpenRoleDropdown(null)}\n />\n <div className=\"absolute right-0 top-full z-20 mt-1 w-36 rounded-lg border border-imp-border bg-imp-background py-1 shadow-lg\">\n {PERMISSION_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n className={`w-full px-3 py-1.5 text-left text-xs ${\n record.permission === opt.value\n ? 'bg-imp-muted font-medium text-imp-foreground'\n : 'text-imp-foreground hover:bg-imp-muted/50'\n }`}\n onClick={() => handleChangeRole(record.id, record, opt.value)}\n >\n {opt.label}\n </button>\n ))}\n <div className=\"my-1 border-t border-imp-border\" />\n <button\n type=\"button\"\n className=\"w-full px-3 py-1.5 text-left text-xs text-red-600 hover:bg-red-500/10 dark:text-red-400\"\n onClick={() => {\n handleRevoke(record.id);\n setOpenRoleDropdown(null);\n }}\n >\n Remove access\n </button>\n </div>\n </>\n )}\n </>\n )}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n\n {/* Grant new access */}\n <div className=\"border-t border-imp-border pt-4\">\n <h3 className=\"mb-2.5 text-xs font-medium uppercase tracking-wide text-imp-muted-foreground\">\n Add people\n </h3>\n <div className=\"flex gap-2\">\n {/* Principal type toggle */}\n <button\n type=\"button\"\n onClick={() => setPrincipalType(principalType === 'user' ? 'team' : 'user')}\n className=\"shrink-0 rounded-lg border border-imp-border bg-imp-background px-2.5 py-1.5 text-xs font-medium text-imp-foreground transition-colors hover:bg-imp-muted/50\"\n >\n {principalType === 'user' ? 'User' : 'Team'}\n </button>\n\n {/* Principal ID input */}\n <input\n type=\"text\"\n value={newPrincipal}\n onChange={(e) => setNewPrincipal(e.target.value)}\n placeholder={principalType === 'user' ? 'User ID' : 'Team ID'}\n className=\"flex-1 rounded-lg border border-imp-border bg-imp-background px-3 py-1.5 text-sm placeholder:text-imp-muted-foreground focus:border-imp-primary/50 focus:outline-none\"\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n handleGrant();\n }\n }}\n />\n\n {/* Permission selector */}\n <button\n type=\"button\"\n onClick={() => {\n const idx = PERMISSION_OPTIONS.findIndex((o) => o.value === newPermission);\n const next = PERMISSION_OPTIONS[(idx + 1) % PERMISSION_OPTIONS.length];\n setNewPermission(next.value);\n }}\n className={`shrink-0 rounded-lg border px-2.5 py-1.5 text-xs font-medium capitalize transition-colors ${getPermissionColor(newPermission)}`}\n >\n {newPermission}\n </button>\n\n {/* Submit */}\n <button\n onClick={handleGrant}\n disabled={grantAccess.isPending}\n className=\"shrink-0 rounded-lg bg-imp-primary px-3.5 py-1.5 text-sm font-medium text-imp-primary-foreground transition-colors hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n <Share2 className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","/**\n * ShareButton — Header action component for the flow editor.\n *\n * Renders a \"Share\" button in the flow header that opens the ShareFlowModal.\n * Registered as a headerAction contribution for the 'flowHeader' context.\n */\n\nimport { useState } from 'react';\nimport { Share2 } from 'lucide-react';\nimport { useAccessibleFlows } from '../hooks/useFlowAccess';\nimport { useRbac } from '../providers/RbacProvider';\nimport { ShareFlowModal } from './ShareFlowModal';\nimport type { HeaderActionProps } from '../types';\n\nexport function ShareButton({ flowId }: HeaderActionProps) {\n const [isOpen, setIsOpen] = useState(false);\n const { isAuthenticated, checkPermission } = useRbac();\n const { data } = useAccessibleFlows();\n\n if (!flowId) {\n return null;\n }\n\n const isAdmin = isAuthenticated && checkPermission('admin:*');\n const myPermission = isAdmin ? 'owner' : (data?.permissions?.[flowId] ?? null);\n\n if (myPermission !== 'owner') {\n return null;\n }\n\n return (\n <>\n <button\n onClick={() => setIsOpen(true)}\n className=\"inline-flex items-center gap-2 rounded-md border border-imp-border px-3 py-1.5 text-sm font-medium text-imp-foreground transition-colors hover:border-imp-primary/50 hover:bg-imp-muted\"\n >\n <Share2 className=\"h-4 w-4\" />\n Share\n </button>\n {isOpen && <ShareFlowModal flowId={flowId} onClose={() => setIsOpen(false)} />}\n </>\n );\n}\n","/**\n * FlowAccessPanel — Panel tab for the flow editor.\n *\n * Shows the current access records for the selected flow in a\n * compact list. Registered as a panelTab contribution for the\n * 'flowEditor' context.\n */\n\nimport { Shield, Users, User } from 'lucide-react';\nimport { useFlowAccess } from '../hooks/useFlowAccess';\nimport { useRbac } from '../providers/RbacProvider';\nimport type { PanelTabProps } from '../types';\n\nexport function FlowAccessPanel({ flowId }: PanelTabProps) {\n const { user } = useRbac();\n const { data, isLoading, error } = useFlowAccess(flowId);\n\n const accessRecords = data?.access ?? [];\n const myRecord = accessRecords.find((r) => r.userId === user?.id);\n\n return (\n <div className=\"flex h-full flex-col p-4\">\n {/* Header */}\n <div className=\"mb-4 flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <Shield className=\"h-4 w-4 text-imp-muted-foreground\" />\n <h3 className=\"text-sm font-medium\">Access Control</h3>\n </div>\n {myRecord && (\n <span className=\"rounded-full border border-imp-border px-2 py-0.5 text-xs font-medium capitalize\">\n {myRecord.permission}\n </span>\n )}\n </div>\n\n {/* Content */}\n {isLoading ? (\n <div className=\"flex flex-1 items-center justify-center\">\n <span className=\"text-sm text-imp-muted-foreground\">Loading access records...</span>\n </div>\n ) : error ? (\n <div className=\"flex flex-1 items-center justify-center\">\n <span className=\"text-sm text-red-500\">\n {error instanceof Error ? error.message : 'Failed to load access records'}\n </span>\n </div>\n ) : accessRecords.length === 0 ? (\n <div className=\"flex flex-1 flex-col items-center justify-center gap-2\">\n <Users className=\"h-8 w-8 text-imp-muted-foreground/50\" />\n <p className=\"text-sm text-imp-muted-foreground\">No access records</p>\n <p className=\"text-xs text-imp-muted-foreground\">Use the Share button to grant access.</p>\n </div>\n ) : (\n <div className=\"flex-1 space-y-1 overflow-y-auto\">\n {accessRecords.map((record) => (\n <div\n key={record.id}\n className=\"flex items-center gap-3 rounded-md px-3 py-2 bg-imp-muted/30\"\n >\n <div className=\"flex h-7 w-7 items-center justify-center rounded-full bg-imp-primary/10\">\n {record.teamId ? (\n <Users className=\"h-3.5 w-3.5 text-imp-primary\" />\n ) : (\n <User className=\"h-3.5 w-3.5 text-imp-primary\" />\n )}\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"truncate text-sm\">\n {record.userId ?? record.teamId}\n {record.userId === user?.id && (\n <span className=\"ml-1 text-imp-muted-foreground\">(you)</span>\n )}\n </p>\n {record.expiresAt && (\n <p className=\"text-xs text-imp-muted-foreground\">\n Expires {new Date(record.expiresAt).toLocaleDateString()}\n </p>\n )}\n </div>\n <span className=\"rounded-full bg-imp-muted px-2 py-0.5 text-xs font-medium capitalize\">\n {record.permission}\n </span>\n </div>\n ))}\n </div>\n )}\n\n {/* Footer — summary */}\n {accessRecords.length > 0 && (\n <div className=\"mt-3 border-t border-imp-border pt-3\">\n <p className=\"text-xs text-imp-muted-foreground\">\n {accessRecords.length} {accessRecords.length === 1 ? 'person' : 'people'} with access\n </p>\n </div>\n )}\n </div>\n );\n}\n","/**\n * useTeams — React Query hooks for team management\n */\n\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { useApiClient } from '@invect/frontend';\nimport type {\n Team,\n TeamWithMembers,\n CreateTeamRequest,\n UpdateTeamRequest,\n AddTeamMemberRequest,\n TeamMember,\n} from '../../shared/types';\n\n/** List all teams */\nexport function useTeams() {\n const api = useApiClient();\n\n return useQuery<{ teams: Team[] }>({\n queryKey: ['rbac', 'teams'],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/teams`, {\n credentials: 'include',\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch teams: ${response.status}`);\n }\n return response.json();\n },\n });\n}\n\n/** Get a single team with members */\nexport function useTeam(teamId: string | undefined) {\n const api = useApiClient();\n\n return useQuery<TeamWithMembers>({\n queryKey: ['rbac', 'team', teamId],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/teams/${teamId}`, {\n credentials: 'include',\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch team: ${response.status}`);\n }\n return response.json();\n },\n enabled: !!teamId,\n });\n}\n\n/** Get current user's teams */\nexport function useMyTeams() {\n const api = useApiClient();\n\n return useQuery<{ teams: Team[] }>({\n queryKey: ['rbac', 'my-teams'],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/my-teams`, {\n credentials: 'include',\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch my teams: ${response.status}`);\n }\n return response.json();\n },\n });\n}\n\n/** Create a team */\nexport function useCreateTeam() {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (input: CreateTeamRequest) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/teams`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify(input),\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to create team: ${response.status}`);\n }\n return response.json() as Promise<Team>;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'teams'] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n },\n });\n}\n\n/** Update a team */\nexport function useUpdateTeam(teamId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (input: UpdateTeamRequest) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/teams/${teamId}`, {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify(input),\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to update team: ${response.status}`);\n }\n return response.json();\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'teams'] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'team', teamId] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n },\n });\n}\n\n/** Delete a team */\nexport function useDeleteTeam() {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (teamId: string) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/teams/${teamId}`, {\n method: 'DELETE',\n credentials: 'include',\n });\n if (!response.ok && response.status !== 204) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to delete team: ${response.status}`);\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'teams'] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n },\n });\n}\n\n/** Add a member to a team */\nexport function useAddTeamMember(teamId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (input: AddTeamMemberRequest) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/teams/${teamId}/members`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify(input),\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to add member: ${response.status}`);\n }\n return response.json() as Promise<TeamMember>;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'team', teamId] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'teams'] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n },\n });\n}\n\n/** Remove a member from a team */\nexport function useRemoveTeamMember(teamId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (userId: string) => {\n const response = await fetch(\n `${api.getBaseURL()}/plugins/rbac/teams/${teamId}/members/${userId}`,\n {\n method: 'DELETE',\n credentials: 'include',\n },\n );\n if (!response.ok && response.status !== 204) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to remove member: ${response.status}`);\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'team', teamId] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'teams'] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n },\n });\n}\n","import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { useApiClient } from '@invect/frontend';\nimport type {\n EffectiveFlowAccessResponse,\n GrantScopeAccessRequest,\n MovePreviewRequest,\n MovePreviewResponse,\n ScopeAccessRecord,\n ScopeTreeResponse,\n} from '../../shared/types';\n\nexport function useScopeTree() {\n const api = useApiClient();\n\n return useQuery<ScopeTreeResponse>({\n queryKey: ['rbac', 'scope-tree'],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/scopes/tree`, {\n credentials: 'include',\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to fetch scope tree: ${response.status}`);\n }\n return response.json();\n },\n });\n}\n\nexport function useScopeAccess(scopeId: string | undefined) {\n const api = useApiClient();\n\n return useQuery<{ access: ScopeAccessRecord[] }>({\n queryKey: ['rbac', 'scope-access', scopeId],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/scopes/${scopeId}/access`, {\n credentials: 'include',\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to fetch scope access: ${response.status}`);\n }\n return response.json();\n },\n enabled: !!scopeId,\n });\n}\n\nexport function useGrantScopeAccess(scopeId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (input: GrantScopeAccessRequest) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/scopes/${scopeId}/access`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify(input),\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to grant scope access: ${response.status}`);\n }\n return response.json() as Promise<ScopeAccessRecord>;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-access', scopeId] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n },\n });\n}\n\nexport function useRevokeScopeAccess(scopeId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (accessId: string) => {\n const response = await fetch(\n `${api.getBaseURL()}/plugins/rbac/scopes/${scopeId}/access/${accessId}`,\n {\n method: 'DELETE',\n credentials: 'include',\n },\n );\n if (!response.ok && response.status !== 204) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to revoke scope access: ${response.status}`);\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-access', scopeId] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n },\n });\n}\n\nexport function useEffectiveFlowAccess(flowId: string | undefined) {\n const api = useApiClient();\n\n return useQuery<EffectiveFlowAccessResponse>({\n queryKey: ['rbac', 'effective-flow-access', flowId],\n queryFn: async () => {\n const response = await fetch(\n `${api.getBaseURL()}/plugins/rbac/flows/${flowId}/effective-access`,\n { credentials: 'include' },\n );\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to fetch effective flow access: ${response.status}`);\n }\n return response.json();\n },\n enabled: !!flowId,\n });\n}\n\nexport function useMoveFlow(flowId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (scopeId: string | null) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/flows/${flowId}/scope`, {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify({ scopeId }),\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to move flow: ${response.status}`);\n }\n return response.json() as Promise<{\n success: boolean;\n flowId: string;\n scopeId: string | null;\n }>;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'accessible-flows'] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'effective-flow-access', flowId] });\n },\n });\n}\n\nexport function usePreviewMove() {\n const api = useApiClient();\n\n return useMutation({\n mutationFn: async (input: MovePreviewRequest) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/preview-move`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify(input),\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to preview move: ${response.status}`);\n }\n return response.json() as Promise<MovePreviewResponse>;\n },\n });\n}\n","import type { FlowAccessPermission, MovePreviewRequest } from '../../../shared/types';\n\nexport interface AuthUser {\n id: string;\n name?: string;\n email?: string;\n}\n\nexport type SelectedItem =\n | { kind: 'flow'; id: string; name: string }\n | { kind: 'team'; id: string; name: string };\n\nexport type PendingMove = MovePreviewRequest & { name: string };\n\nexport type PrincipalSelection = { type: 'user' | 'team'; id: string };\n\nexport interface AccessRow {\n id: string;\n label: string;\n kind: 'user' | 'team';\n permission: FlowAccessPermission | null;\n source: string;\n group?: string;\n canRemove: boolean;\n onPermissionChange?: (permission: FlowAccessPermission) => void;\n onRemove?: () => void;\n}\n\nexport function formatPermissionLabel(permission: FlowAccessPermission): string {\n switch (permission) {\n case 'owner':\n return 'Owner';\n case 'editor':\n return 'Editor';\n case 'operator':\n return 'Operator';\n case 'viewer':\n default:\n return 'Viewer';\n }\n}\n\nexport function getPermissionBadgeClasses(_permission: FlowAccessPermission): string {\n return 'border-imp-border text-imp-muted-foreground';\n}\n","import { useQuery } from '@tanstack/react-query';\nimport { useApiClient } from '@invect/frontend';\nimport type { AuthUser } from './types';\n\nexport function useUsers(): AuthUser[] {\n const api = useApiClient();\n\n const { data } = useQuery<{ users: AuthUser[] }>({\n queryKey: ['rbac', 'auth-users'],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/auth/users?limit=200`, {\n credentials: 'include',\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch users: ${response.status}`);\n }\n return response.json();\n },\n staleTime: 1000 * 60 * 5, // 5 min — shared across all consumers\n gcTime: 1000 * 60 * 10,\n });\n\n return data?.users ?? [];\n}\n","import { Fragment, useState } from 'react';\nimport { clsx } from 'clsx';\nimport { ChevronDown, Trash2, User, Users } from 'lucide-react';\nimport {\n Dialog,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@invect/frontend';\nimport { twMerge } from 'tailwind-merge';\nimport type { AccessRow } from './types';\nimport type { FlowAccessPermission } from '../../../shared/types';\nimport { getPermissionBadgeClasses } from './types';\n\nfunction cn(...inputs: Parameters<typeof clsx>) {\n return twMerge(clsx(inputs));\n}\n\nconst ROLE_OPTIONS: Array<{\n value: FlowAccessPermission;\n label: string;\n description: string;\n}> = [\n { value: 'viewer', label: 'Viewer', description: 'Can inspect the flow.' },\n { value: 'operator', label: 'Operator', description: 'Can inspect and run the flow.' },\n { value: 'editor', label: 'Editor', description: 'Can inspect, run, and edit the flow.' },\n { value: 'owner', label: 'Owner', description: 'Can edit and manage sharing.' },\n];\n\nexport function RoleSelector({\n value,\n onChange,\n}: {\n value: FlowAccessPermission;\n onChange: (permission: FlowAccessPermission) => void;\n}) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n className={cn(\n 'inline-flex w-full items-center justify-between gap-1 rounded-md border px-2.5 py-1.5 text-sm font-medium capitalize',\n getPermissionBadgeClasses(value),\n )}\n >\n <span className=\"truncate\">{value}</span>\n <ChevronDown className=\"h-3.5 w-3.5 shrink-0\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-56\">\n <DropdownMenuLabel className=\"text-xs\">Select role</DropdownMenuLabel>\n <DropdownMenuSeparator />\n {ROLE_OPTIONS.map((role) => (\n <DropdownMenuItem\n key={role.value}\n onSelect={() => onChange(role.value)}\n className={cn(\n 'items-start gap-0 px-2 py-2',\n value === role.value && 'bg-accent text-accent-foreground',\n )}\n >\n <div className=\"min-w-0 text-left\">\n <div className=\"text-sm font-medium\">{role.label}</div>\n <div className=\"text-xs text-muted-foreground\">{role.description}</div>\n </div>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport function OptionalRoleSelector({\n value,\n onChange,\n emptyLabel = 'No direct access',\n}: {\n value: FlowAccessPermission | null;\n onChange: (permission: FlowAccessPermission | null) => void;\n emptyLabel?: string;\n}) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n className={cn(\n 'inline-flex w-40 items-center justify-between gap-1 rounded-md border px-2.5 py-1.5 text-sm font-medium capitalize',\n value\n ? getPermissionBadgeClasses(value)\n : 'border-imp-border text-imp-muted-foreground hover:bg-imp-muted/50',\n )}\n >\n <span className=\"truncate\">{value ?? emptyLabel}</span>\n <ChevronDown className=\"h-3.5 w-3.5 shrink-0\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-56\">\n <DropdownMenuLabel className=\"text-xs\">Set access level</DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onSelect={() => onChange(null)}\n className={cn('px-2 py-2 text-sm', value === null && 'bg-accent text-accent-foreground')}\n >\n {emptyLabel}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n {ROLE_OPTIONS.map((role) => (\n <DropdownMenuItem\n key={role.value}\n onSelect={() => onChange(role.value)}\n className={cn(\n 'items-start gap-0 px-2 py-2',\n value === role.value && 'bg-accent text-accent-foreground',\n )}\n >\n <div className=\"min-w-0 text-left\">\n <div className=\"text-sm font-medium\">{role.label}</div>\n <div className=\"text-xs text-muted-foreground\">{role.description}</div>\n </div>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport function AccessTable({\n rows,\n isLoading,\n emptyLabel,\n}: {\n rows: AccessRow[];\n isLoading: boolean;\n emptyLabel: string;\n}) {\n const [pendingRemovalRow, setPendingRemovalRow] = useState<AccessRow | null>(null);\n\n const removalDialogCopy = pendingRemovalRow\n ? pendingRemovalRow.group === 'Members'\n ? {\n title: 'Remove team member',\n body: `Remove \"${pendingRemovalRow.label}\" from team?`,\n confirmLabel: 'Remove member',\n }\n : {\n title: pendingRemovalRow.kind === 'team' ? 'Revoke team access' : 'Revoke user access',\n body:\n pendingRemovalRow.kind === 'team'\n ? `Remove direct access for ${pendingRemovalRow.label}?`\n : `Remove direct access for ${pendingRemovalRow.label}?`,\n confirmLabel: 'Remove access',\n }\n : null;\n\n if (isLoading) {\n return <div className=\"px-2 py-4 text-sm text-center text-imp-muted-foreground\">Loading…</div>;\n }\n if (rows.length === 0) {\n return (\n <div className=\"px-2 py-4 text-sm text-center text-imp-muted-foreground\">{emptyLabel}</div>\n );\n }\n\n const groups: Array<{ label: string; rows: AccessRow[] }> = [];\n for (const row of rows) {\n const groupLabel = row.group ?? '';\n const existing = groups.find((g) => g.label === groupLabel);\n if (existing) {\n existing.rows.push(row);\n } else {\n groups.push({ label: groupLabel, rows: [row] });\n }\n }\n const hasGroups = groups.length > 1;\n\n return (\n <>\n <table className=\"w-full text-sm table-fixed\">\n <colgroup>\n <col />\n <col className=\"w-36\" />\n <col className=\"w-10\" />\n </colgroup>\n <tbody>\n {groups.map((group) => (\n <Fragment key={group.label || '_default'}>\n {hasGroups && group.label && (\n <tr>\n <td\n colSpan={3}\n className=\"px-3 pt-4 pb-1.5 text-[10px] font-semibold uppercase tracking-wider text-imp-muted-foreground\"\n >\n {group.label}\n </td>\n </tr>\n )}\n {group.rows.map((row, rowIndex) => (\n <tr\n key={row.id}\n className={cn(\n 'hover:bg-imp-muted/20',\n rowIndex > 0 && 'border-t border-imp-border',\n )}\n >\n <td className=\"px-3 py-2.5\">\n <div className=\"flex items-center gap-3\">\n <div\n className={cn(\n 'flex h-7 w-7 shrink-0 items-center justify-center rounded-full',\n row.kind === 'user' ? 'bg-imp-primary/10' : 'bg-imp-muted',\n )}\n >\n {row.kind === 'user' ? (\n <User className=\"h-3.5 w-3.5 text-imp-primary\" />\n ) : (\n <Users className=\"h-3.5 w-3.5 text-imp-muted-foreground\" />\n )}\n </div>\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium truncate\">{row.label}</span>\n {row.kind === 'team' && (\n <span className=\"shrink-0 rounded border border-imp-border px-1.5 py-0.5 text-[11px] font-medium text-imp-muted-foreground\">\n Team\n </span>\n )}\n </div>\n {row.source && row.source !== 'Direct grant' && row.source !== 'Member' && (\n <span className=\"text-[11px] text-imp-muted-foreground\">\n {row.source}\n </span>\n )}\n </div>\n </div>\n </td>\n <td className=\"px-3 py-2.5 text-center\">\n {row.permission ? (\n row.onPermissionChange ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n className={cn(\n 'inline-flex w-32 items-center justify-between gap-1 rounded-full border px-2.5 py-1 text-xs font-medium capitalize hover:bg-imp-muted/50',\n getPermissionBadgeClasses(row.permission),\n )}\n title={row.source}\n >\n <span className=\"truncate\">{row.permission}</span>\n <ChevronDown className=\"h-3.5 w-3.5 shrink-0\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-64\">\n <DropdownMenuLabel className=\"text-xs\">\n Change access role\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n {ROLE_OPTIONS.map((role) => (\n <DropdownMenuItem\n key={role.value}\n onSelect={() => row.onPermissionChange?.(role.value)}\n className={cn(\n 'items-start gap-0 px-2 py-2',\n row.permission === role.value &&\n 'bg-accent text-accent-foreground',\n )}\n >\n <div className=\"min-w-0 text-left\">\n <div className=\"text-sm font-medium\">{role.label}</div>\n <div className=\"text-xs text-muted-foreground\">\n {role.description}\n </div>\n </div>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n ) : (\n <span\n className={cn(\n 'inline-flex w-32 justify-center rounded-full border px-2.5 py-1 text-xs font-medium capitalize',\n getPermissionBadgeClasses(row.permission),\n )}\n title={row.source}\n >\n {row.permission}\n </span>\n )\n ) : null}\n </td>\n <td className=\"px-3 py-2.5 text-center\">\n {row.canRemove && row.onRemove ? (\n <button\n type=\"button\"\n onClick={() => setPendingRemovalRow(row)}\n className=\"p-1 rounded text-imp-muted-foreground hover:bg-red-500/10 hover:text-red-500\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </button>\n ) : null}\n </td>\n </tr>\n ))}\n </Fragment>\n ))}\n </tbody>\n </table>\n\n <Dialog\n open={!!pendingRemovalRow}\n onOpenChange={(open) => !open && setPendingRemovalRow(null)}\n >\n <DialogContent className=\"max-w-sm border-imp-border bg-imp-background text-imp-foreground sm:max-w-sm\">\n <DialogHeader>\n <DialogTitle className=\"text-sm font-semibold\">{removalDialogCopy?.title}</DialogTitle>\n </DialogHeader>\n <p className=\"text-sm text-imp-muted-foreground\">{removalDialogCopy?.body}</p>\n <DialogFooter className=\"justify-between w-full sm:gap-2\">\n <button\n type=\"button\"\n onClick={() => setPendingRemovalRow(null)}\n className=\"rounded-md mr-auto border border-imp-border px-3 py-1.5 text-xs font-medium text-imp-muted-foreground hover:text-imp-foreground\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={() => {\n pendingRemovalRow?.onRemove?.();\n setPendingRemovalRow(null);\n }}\n className=\"rounded-md bg-red-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-red-700\"\n >\n {removalDialogCopy?.confirmLabel}\n </button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@invect/frontend';\n\nexport function FormDialog({\n open,\n onClose,\n title,\n children,\n}: {\n open: boolean;\n onClose: () => void;\n title: string;\n children: React.ReactNode;\n}) {\n return (\n <Dialog open={open} onOpenChange={(nextOpen) => !nextOpen && onClose()}>\n <DialogContent className=\"max-w-md p-4 border-imp-border bg-imp-background text-imp-foreground sm:max-w-md\">\n <DialogHeader className=\"mb-1\">\n <DialogTitle className=\"text-sm font-semibold\">{title}</DialogTitle>\n </DialogHeader>\n {children}\n </DialogContent>\n </Dialog>\n );\n}\n","import { useRef, useState } from 'react';\nimport { User, X } from 'lucide-react';\nimport type { AuthUser } from './types';\n\nexport function MemberCombobox({\n users,\n excludeIds,\n selectedUserIds,\n onSelect,\n}: {\n users: AuthUser[];\n excludeIds: Set<string>;\n selectedUserIds: string[];\n onSelect: (userIds: string[]) => void;\n}) {\n const [query, setQuery] = useState('');\n const [open, setOpen] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const selectedSet = new Set(selectedUserIds);\n\n const filteredUsers = users.filter((user) => {\n if (excludeIds.has(user.id)) {\n return false;\n }\n if (selectedSet.has(user.id)) {\n return false;\n }\n const haystack = `${user.name || ''} ${user.email || ''} ${user.id}`.toLowerCase();\n return haystack.includes(query.toLowerCase());\n });\n\n const toggle = (userId: string) => {\n onSelect(\n selectedSet.has(userId)\n ? selectedUserIds.filter((id) => id !== userId)\n : [...selectedUserIds, userId],\n );\n };\n\n return (\n <div\n ref={containerRef}\n className=\"relative\"\n onBlur={(e) => {\n if (!containerRef.current?.contains(e.relatedTarget as Node)) {\n setOpen(false);\n }\n }}\n >\n <div\n className=\"flex min-h-[2.5rem] w-full cursor-text flex-wrap gap-1.5 rounded-md border border-imp-border bg-imp-background px-2 py-1.5 focus-within:border-imp-primary/50\"\n onClick={() => setOpen(true)}\n >\n {selectedUserIds.map((userId) => {\n const user = users.find((u) => u.id === userId);\n const label = user?.name || user?.email || userId;\n return (\n <span\n key={userId}\n className=\"inline-flex items-center gap-1 rounded-md border border-imp-border bg-imp-muted px-2 py-0.5 text-xs font-medium text-imp-foreground\"\n >\n <User className=\"h-3 w-3 shrink-0 text-imp-muted-foreground\" />\n <span className=\"max-w-[140px] truncate\">{label}</span>\n <button\n type=\"button\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={(e) => {\n e.stopPropagation();\n toggle(userId);\n }}\n className=\"ml-0.5 text-imp-muted-foreground hover:text-imp-foreground\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </span>\n );\n })}\n <input\n value={query}\n onChange={(e) => {\n setQuery(e.target.value);\n setOpen(true);\n }}\n onFocus={() => setOpen(true)}\n placeholder={selectedUserIds.length === 0 ? 'Search users…' : 'Add more…'}\n className=\"min-w-[120px] flex-1 bg-transparent text-sm outline-none placeholder:text-imp-muted-foreground\"\n />\n </div>\n {open && (\n <div className=\"absolute left-0 z-20 mt-1 w-full overflow-y-auto rounded-md border border-imp-border bg-imp-background shadow-lg top-full max-h-52\">\n {filteredUsers.length === 0 ? (\n <div className=\"px-3 py-2 text-xs text-imp-muted-foreground\">\n {query ? 'No matches.' : 'No more users to add.'}\n </div>\n ) : (\n filteredUsers.map((user) => (\n <button\n key={user.id}\n type=\"button\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n toggle(user.id);\n setQuery('');\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-imp-muted/50\"\n >\n <User className=\"h-4 w-4 shrink-0 text-imp-muted-foreground\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate font-medium\">{user.name || user.email || user.id}</div>\n {user.name && user.email && (\n <div className=\"truncate text-xs text-imp-muted-foreground\">{user.email}</div>\n )}\n </div>\n </button>\n ))\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useMemo, useState } from 'react';\nimport { ChevronRight, Plus, Trash2, Users } from 'lucide-react';\nimport { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@invect/frontend';\nimport {\n useAddTeamMember,\n useDeleteTeam,\n useTeam,\n useRemoveTeamMember,\n} from '../../hooks/useTeams';\nimport { useGrantScopeAccess, useRevokeScopeAccess, useScopeAccess } from '../../hooks/useScopes';\nimport type { FlowAccessPermission, Team } from '../../../shared/types';\nimport type { AccessRow, AuthUser } from './types';\nimport { formatPermissionLabel, getPermissionBadgeClasses } from './types';\nimport { AccessTable, OptionalRoleSelector, RoleSelector } from './AccessTable';\nimport { FormDialog } from './FormDialog';\nimport { MemberCombobox } from './MemberCombobox';\n\nexport function ScopeDetailPanel({\n scopeId,\n scopeName,\n users,\n userMap,\n teams,\n isAdmin,\n}: {\n scopeId: string;\n scopeName: string;\n users: AuthUser[];\n userMap: Map<string, AuthUser>;\n teams: Team[];\n isAdmin: boolean;\n}) {\n const scopeQuery = useTeam(scopeId);\n const scopeAccessQuery = useScopeAccess(scopeId);\n const grantScopeAccess = useGrantScopeAccess(scopeId);\n const revokeScopeAccess = useRevokeScopeAccess(scopeId);\n const addTeamMember = useAddTeamMember(scopeId);\n const removeTeamMember = useRemoveTeamMember(scopeId);\n const deleteScope = useDeleteTeam();\n\n const [showGrantDialog, setShowGrantDialog] = useState(false);\n const [showMemberDialog, setShowMemberDialog] = useState(false);\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [permission, setPermission] = useState<FlowAccessPermission>('viewer');\n const [grantUserIds, setGrantUserIds] = useState<string[]>([]);\n const [memberUserIds, setMemberUserIds] = useState<string[]>([]);\n\n const members = scopeQuery.data?.members ?? [];\n const scopeAccess = scopeAccessQuery.data?.access ?? [];\n const existingMemberIds = new Set(members.map((member) => member.userId));\n const existingScopeUserIds = new Set(\n scopeAccess.map((record) => record.userId).filter(Boolean) as string[],\n );\n const teamRoleRecord = scopeAccess.find((record) => record.teamId === scopeId) ?? null;\n const childTeams = teams.filter((team) => team.parentId === scopeId);\n\n const isLoading = scopeQuery.isLoading || scopeAccessQuery.isLoading;\n\n const accessRows = useMemo(() => {\n const rows: AccessRow[] = [];\n for (const member of members) {\n const user = userMap.get(member.userId);\n rows.push({\n id: `member:${member.id}`,\n label: user?.name || user?.email || member.userId,\n kind: 'user',\n permission: null,\n source: 'Member',\n group: 'Members',\n canRemove: isAdmin,\n onRemove: () => removeTeamMember.mutate(member.userId),\n });\n }\n for (const record of scopeAccess) {\n if (record.teamId === scopeId) {\n continue;\n }\n const isUser = !!record.userId;\n const userId = record.userId ?? null;\n rows.push({\n id: `access:${record.id}`,\n label: isUser\n ? userMap.get(userId ?? '')?.name ||\n userMap.get(userId ?? '')?.email ||\n userId ||\n 'Unknown'\n : teams.find((team) => team.id === record.teamId)?.name || record.teamId || 'Unknown',\n kind: isUser ? 'user' : 'team',\n permission: record.permission,\n source: 'Direct grant',\n group: 'Access Grants',\n canRemove: isAdmin,\n onPermissionChange: userId\n ? (permission) =>\n grantScopeAccess.mutate({\n userId,\n permission,\n })\n : undefined,\n onRemove: () => revokeScopeAccess.mutate(record.id),\n });\n }\n return rows;\n }, [\n members,\n scopeAccess,\n userMap,\n teams,\n isAdmin,\n removeTeamMember,\n grantScopeAccess,\n revokeScopeAccess,\n ]);\n\n const memberRows = accessRows.filter((row) => row.group === 'Members');\n const grantRows = accessRows.filter((row) => row.group === 'Access Grants');\n\n const scopePath = useMemo(() => {\n const path: Team[] = [];\n let current = teams.find((team) => team.id === scopeId) ?? null;\n while (current) {\n path.unshift(current);\n current = current.parentId\n ? (teams.find((team) => team.id === current?.parentId) ?? null)\n : null;\n }\n return path;\n }, [teams, scopeId]);\n\n return (\n <div className=\"flex flex-col h-full overflow-hidden\">\n <div className=\"px-5 py-4 overflow-hidden border-b shrink-0 border-imp-border\">\n <div className=\"flex items-start gap-3\">\n <div className=\"flex items-center justify-center flex-none w-10 h-10 rounded-xl bg-imp-primary/10 text-imp-primary\">\n <Users className=\"w-5 h-5\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <h2 className=\"flex-1 min-w-0 text-base font-semibold truncate\">{scopeName}</h2>\n {isAdmin ? (\n <div className=\"flex items-center gap-1.5\">\n <button\n type=\"button\"\n onClick={() => setShowDeleteConfirm(true)}\n className=\"flex items-center gap-1.5 rounded-md border border-red-200 px-3 py-1.5 text-xs font-medium text-red-600 transition-colors hover:bg-red-500/10 dark:border-red-500/20 dark:text-red-400\"\n >\n <Trash2 className=\"w-4 h-4\" /> Delete team\n </button>\n </div>\n ) : null}\n </div>\n <div className=\"flex flex-wrap items-center gap-1 mt-1 text-[11px] text-imp-muted-foreground\">\n <span>Root</span>\n {scopePath.map((team) => (\n <div key={team.id} className=\"flex items-center gap-1\">\n <ChevronRight className=\"w-3 h-3\" />\n <span\n className={team.id === scopeId ? 'font-medium text-imp-foreground' : undefined}\n >\n {team.name}\n </span>\n </div>\n ))}\n </div>\n </div>\n </div>\n <div className=\"flex items-center justify-between\">\n <p className=\"mt-3 text-xs text-imp-muted-foreground\">\n Access applies to all flows inside this team and its child teams.\n </p>\n </div>\n </div>\n\n <div className=\"flex-1 px-5 py-4 overflow-x-hidden overflow-y-auto\">\n <div className=\"space-y-6\">\n <section>\n <div className=\"flex items-center justify-between gap-4\">\n <div className=\"min-w-0\">\n <h3 className=\"text-sm font-semibold text-imp-foreground\">\n Team Role on Child Flows\n </h3>\n <p className=\"mt-0.5 text-xs text-imp-muted-foreground\">\n Base role applied to every flow inside this team.\n </p>\n </div>\n <div className=\"shrink-0\">\n <OptionalRoleSelector\n value={teamRoleRecord?.permission ?? null}\n emptyLabel=\"No team role\"\n onChange={(nextPermission) => {\n if (nextPermission === null) {\n if (teamRoleRecord) {\n revokeScopeAccess.mutate(teamRoleRecord.id);\n }\n return;\n }\n\n grantScopeAccess.mutate({\n teamId: scopeId,\n permission: nextPermission,\n });\n }}\n />\n </div>\n </div>\n </section>\n\n <section className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"text-sm font-semibold text-imp-foreground\">Members</h3>\n {isAdmin ? (\n <button\n type=\"button\"\n onClick={() => setShowMemberDialog(true)}\n className=\"flex items-center gap-1.5 rounded-md border border-imp-border px-3 py-1.5 text-xs font-medium text-imp-muted-foreground transition-colors hover:border-imp-primary/50 hover:text-imp-foreground\"\n >\n <Plus className=\"w-4 h-4\" /> Add Member\n </button>\n ) : null}\n </div>\n <div className=\"overflow-hidden border rounded-xl border-imp-border bg-imp-background/40\">\n <AccessTable rows={memberRows} isLoading={isLoading} emptyLabel=\"No members\" />\n </div>\n </section>\n\n {childTeams.length > 0 ? (\n <section className=\"space-y-2\">\n <h3 className=\"text-sm font-semibold text-imp-foreground\">Sub-teams</h3>\n <div className=\"space-y-2\">\n {childTeams.map((team) => (\n <div\n key={team.id}\n className=\"flex items-center gap-2 px-3 py-2 border rounded-xl border-imp-border bg-imp-background/40\"\n >\n <Users className=\"w-3.5 h-3.5 text-imp-muted-foreground\" />\n <span className=\"flex-1 min-w-0 text-sm font-medium truncate text-imp-foreground\">\n {team.name}\n </span>\n <span className=\"text-[11px] text-imp-muted-foreground\">Child team</span>\n </div>\n ))}\n </div>\n </section>\n ) : null}\n </div>\n </div>\n\n <FormDialog\n open={showGrantDialog}\n onClose={() => setShowGrantDialog(false)}\n title=\"Grant Scope Access\"\n >\n <div className=\"flex flex-col gap-3\">\n <MemberCombobox\n users={users}\n excludeIds={existingScopeUserIds}\n selectedUserIds={grantUserIds}\n onSelect={setGrantUserIds}\n />\n <div className=\"flex items-center gap-2\">\n <RoleSelector value={permission} onChange={setPermission} />\n <button\n type=\"button\"\n onClick={() => {\n if (grantUserIds.length === 0) {\n return;\n }\n for (const userId of grantUserIds) {\n grantScopeAccess.mutate({ userId, permission });\n }\n setGrantUserIds([]);\n setShowGrantDialog(false);\n }}\n disabled={grantUserIds.length === 0 || grantScopeAccess.isPending}\n className=\"ml-auto rounded-md bg-imp-primary px-4 py-2 text-sm font-semibold text-imp-primary-foreground hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n Grant\n </button>\n </div>\n </div>\n </FormDialog>\n\n <FormDialog\n open={showMemberDialog}\n onClose={() => setShowMemberDialog(false)}\n title=\"Add Team Member\"\n >\n <div className=\"flex flex-col gap-3\">\n <MemberCombobox\n users={users}\n excludeIds={existingMemberIds}\n selectedUserIds={memberUserIds}\n onSelect={setMemberUserIds}\n />\n <button\n type=\"button\"\n onClick={() => {\n if (memberUserIds.length === 0) {\n return;\n }\n for (const userId of memberUserIds) {\n addTeamMember.mutate({ userId });\n }\n setMemberUserIds([]);\n setShowMemberDialog(false);\n }}\n disabled={memberUserIds.length === 0 || addTeamMember.isPending}\n className=\"rounded-md bg-imp-primary px-4 py-2 text-sm font-semibold text-imp-primary-foreground hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n Add\n </button>\n </div>\n </FormDialog>\n\n <Dialog\n open={showDeleteConfirm}\n onOpenChange={(open) => !open && setShowDeleteConfirm(false)}\n >\n <DialogContent className=\"max-w-sm border-imp-border bg-imp-background text-imp-foreground sm:max-w-sm\">\n <DialogHeader>\n <DialogTitle className=\"text-sm font-semibold\">Delete team</DialogTitle>\n </DialogHeader>\n <p className=\"text-sm text-imp-muted-foreground\">\n Are you sure you want to delete{' '}\n <strong className=\"text-imp-foreground\">{scopeName}</strong>? Flows directly inside this\n team will move to the parent team when one exists, and this team's access grants will be\n removed.\n </p>\n <DialogFooter className=\"gap-2 sm:gap-0\">\n <button\n type=\"button\"\n onClick={() => setShowDeleteConfirm(false)}\n className=\"rounded-md border border-imp-border px-3 py-1.5 text-xs font-medium text-imp-muted-foreground hover:text-imp-foreground\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={() => {\n deleteScope.mutate(scopeId);\n setShowDeleteConfirm(false);\n }}\n className=\"rounded-md bg-red-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-red-700\"\n >\n Delete\n </button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n );\n}\n","import { useRef, useState } from 'react';\nimport { User, Users, X } from 'lucide-react';\nimport type { Team } from '../../../shared/types';\nimport type { AuthUser, PrincipalSelection } from './types';\n\nexport function PrincipalCombobox({\n users,\n teams,\n excludeUserIds,\n excludeTeamIds,\n selections,\n onSelect,\n}: {\n users: AuthUser[];\n teams: Team[];\n excludeUserIds: Set<string | null | undefined>;\n excludeTeamIds: Set<string | null | undefined>;\n selections: PrincipalSelection[];\n onSelect: (selections: PrincipalSelection[]) => void;\n}) {\n const [query, setQuery] = useState('');\n const [open, setOpen] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const selectedUserIds = new Set(selections.filter((s) => s.type === 'user').map((s) => s.id));\n const selectedTeamIds = new Set(selections.filter((s) => s.type === 'team').map((s) => s.id));\n\n const filteredUsers = users.filter((user) => {\n if (excludeUserIds.has(user.id)) {\n return false;\n }\n if (selectedUserIds.has(user.id)) {\n return false;\n }\n const haystack = `${user.name || ''} ${user.email || ''} ${user.id}`.toLowerCase();\n return haystack.includes(query.toLowerCase());\n });\n\n const filteredTeams = teams.filter((team) => {\n if (excludeTeamIds.has(team.id)) {\n return false;\n }\n if (selectedTeamIds.has(team.id)) {\n return false;\n }\n const haystack = `${team.name} ${team.description || ''}`.toLowerCase();\n return haystack.includes(query.toLowerCase());\n });\n\n const toggle = (sel: PrincipalSelection) => {\n const exists = selections.some((s) => s.type === sel.type && s.id === sel.id);\n onSelect(\n exists\n ? selections.filter((s) => !(s.type === sel.type && s.id === sel.id))\n : [...selections, sel],\n );\n };\n\n const getLabel = (sel: PrincipalSelection): string => {\n if (sel.type === 'user') {\n const user = users.find((u) => u.id === sel.id);\n return user?.name || user?.email || sel.id;\n }\n return teams.find((t) => t.id === sel.id)?.name || sel.id;\n };\n\n return (\n <div\n ref={containerRef}\n className=\"relative\"\n onBlur={(e) => {\n if (!containerRef.current?.contains(e.relatedTarget as Node)) {\n setOpen(false);\n }\n }}\n >\n <div\n className=\"flex min-h-[2.5rem] w-full cursor-text flex-wrap gap-1.5 rounded-md border border-imp-border bg-imp-background px-2 py-1.5 focus-within:border-imp-primary/50\"\n onClick={() => setOpen(true)}\n >\n {selections.map((sel) => (\n <span\n key={`${sel.type}:${sel.id}`}\n className=\"inline-flex items-center gap-1 rounded-md border border-imp-border bg-imp-muted px-2 py-0.5 text-xs font-medium text-imp-foreground\"\n >\n {sel.type === 'user' ? (\n <User className=\"h-3 w-3 shrink-0 text-imp-muted-foreground\" />\n ) : (\n <Users className=\"h-3 w-3 shrink-0 text-imp-muted-foreground\" />\n )}\n <span className=\"max-w-[140px] truncate\">{getLabel(sel)}</span>\n <button\n type=\"button\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={(e) => {\n e.stopPropagation();\n toggle(sel);\n }}\n className=\"ml-0.5 text-imp-muted-foreground hover:text-imp-foreground\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </span>\n ))}\n <input\n value={query}\n onChange={(e) => {\n setQuery(e.target.value);\n setOpen(true);\n }}\n onFocus={() => setOpen(true)}\n placeholder={selections.length === 0 ? 'Search users or teams…' : 'Add more…'}\n className=\"min-w-[120px] flex-1 bg-transparent text-sm outline-none placeholder:text-imp-muted-foreground\"\n />\n </div>\n {open && (\n <div className=\"absolute left-0 z-20 mt-1 w-full overflow-y-auto rounded-md border border-imp-border bg-imp-background shadow-lg top-full max-h-52\">\n {filteredTeams.length === 0 && filteredUsers.length === 0 ? (\n <div className=\"px-3 py-2 text-xs text-imp-muted-foreground\">\n {query ? 'No matches.' : 'No more users or teams to add.'}\n </div>\n ) : (\n <>\n {filteredTeams.length > 0 && (\n <>\n <div className=\"px-3 py-1 text-[10px] font-medium uppercase tracking-wider text-imp-muted-foreground\">\n Teams\n </div>\n {filteredTeams.map((team) => (\n <button\n key={team.id}\n type=\"button\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n toggle({ type: 'team', id: team.id });\n setQuery('');\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-imp-muted/50\"\n >\n <Users className=\"h-4 w-4 shrink-0 text-imp-muted-foreground\" />\n <span className=\"truncate font-medium\">{team.name}</span>\n </button>\n ))}\n </>\n )}\n {filteredUsers.length > 0 && (\n <>\n <div className=\"px-3 py-1 text-[10px] font-medium uppercase tracking-wider text-imp-muted-foreground\">\n Users\n </div>\n {filteredUsers.map((user) => (\n <button\n key={user.id}\n type=\"button\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n toggle({ type: 'user', id: user.id });\n setQuery('');\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-imp-muted/50\"\n >\n <User className=\"h-4 w-4 shrink-0 text-imp-muted-foreground\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate font-medium\">\n {user.name || user.email || user.id}\n </div>\n {user.name && user.email && (\n <div className=\"truncate text-xs text-imp-muted-foreground\">\n {user.email}\n </div>\n )}\n </div>\n </button>\n ))}\n </>\n )}\n </>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useMemo, useState } from 'react';\nimport { ChevronRight, ExternalLink, Plus, Workflow } from 'lucide-react';\nimport { useGrantFlowAccess, useRevokeFlowAccess } from '../../hooks/useFlowAccess';\nimport { useEffectiveFlowAccess } from '../../hooks/useScopes';\nimport type { FlowAccessPermission, Team } from '../../../shared/types';\nimport type { AccessRow, AuthUser, PrincipalSelection } from './types';\nimport { AccessTable, RoleSelector } from './AccessTable';\nimport { FormDialog } from './FormDialog';\nimport { PrincipalCombobox } from './PrincipalCombobox';\n\nexport function FlowDetailPanel({\n flowId,\n flowName,\n users,\n userMap,\n teams,\n isAdmin,\n}: {\n flowId: string;\n flowName: string;\n users: AuthUser[];\n userMap: Map<string, AuthUser>;\n teams: Team[];\n isAdmin: boolean;\n}) {\n const effectiveFlowAccessQuery = useEffectiveFlowAccess(flowId);\n const grantFlowAccess = useGrantFlowAccess(flowId);\n const revokeFlowAccess = useRevokeFlowAccess(flowId);\n const [showGrantDialog, setShowGrantDialog] = useState(false);\n const [principalSelections, setPrincipalSelections] = useState<PrincipalSelection[]>([]);\n const [permission, setPermission] = useState<FlowAccessPermission>('viewer');\n\n const effectiveRecords = effectiveFlowAccessQuery.data?.records ?? [];\n const existingDirectUserIds = new Set(\n effectiveRecords\n .filter((record) => record.source === 'direct' && record.userId)\n .map((record) => record.userId),\n );\n const existingDirectTeamIds = new Set(\n effectiveRecords\n .filter((record) => record.source === 'direct' && record.teamId)\n .map((record) => record.teamId),\n );\n const owningTeam =\n teams.find((team) => team.id === effectiveFlowAccessQuery.data?.scopeId) ?? null;\n const scopePath = useMemo(() => {\n const path: Team[] = [];\n let current = owningTeam;\n\n while (current) {\n path.unshift(current);\n current = current.parentId\n ? (teams.find((team) => team.id === current?.parentId) ?? null)\n : null;\n }\n\n return path;\n }, [owningTeam, teams]);\n\n const accessRows = useMemo(() => {\n const rows: AccessRow[] = effectiveRecords.map((record) => {\n const isUser = !!record.userId;\n const userId = record.userId ?? null;\n const teamId = record.teamId ?? null;\n\n return {\n id: `${record.source}:${record.id}`,\n label: isUser\n ? userMap.get(userId ?? '')?.name ||\n userMap.get(userId ?? '')?.email ||\n userId ||\n 'Unknown'\n : teams.find((team) => team.id === teamId)?.name || teamId || 'Unknown',\n kind: isUser ? 'user' : 'team',\n permission: record.permission,\n source: record.source === 'direct' ? 'Direct grant' : `via ${record.scopeName || 'team'}`,\n group: record.source === 'direct' ? 'Direct' : 'Inherited',\n canRemove: record.source === 'direct' && isAdmin,\n onPermissionChange:\n record.source === 'direct'\n ? (permission) =>\n grantFlowAccess.mutate({\n ...(userId ? { userId } : teamId ? { teamId } : {}),\n permission,\n })\n : undefined,\n onRemove: () => revokeFlowAccess.mutate(record.id),\n };\n });\n\n rows.sort((a, b) => {\n const aIsDirect = a.source === 'Direct grant' ? 1 : 0;\n const bIsDirect = b.source === 'Direct grant' ? 1 : 0;\n return bIsDirect - aIsDirect;\n });\n\n return rows;\n }, [effectiveRecords, userMap, teams, isAdmin, grantFlowAccess, revokeFlowAccess]);\n\n const directRows = accessRows.filter((row) => row.group === 'Direct');\n const inheritedRows = accessRows.filter((row) => row.group === 'Inherited');\n\n const openFlow = () => {\n const path = window.location.pathname;\n const accessIdx = path.lastIndexOf('/access');\n const basePath = accessIdx >= 0 ? path.slice(0, accessIdx) : path;\n window.open(`${basePath}/flow/${flowId}`, '_blank');\n };\n\n return (\n <div className=\"flex flex-col h-full overflow-hidden\">\n <div className=\"px-5 py-4 overflow-hidden border-b shrink-0 border-imp-border\">\n <div className=\"flex items-start gap-3\">\n <div className=\"flex items-center justify-center flex-none w-10 h-10 rounded-xl bg-imp-primary/10 text-imp-primary\">\n <Workflow className=\"w-5 h-5\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <h2 className=\"flex-1 min-w-0 text-base font-semibold truncate\">{flowName}</h2>\n </div>\n <div className=\"mt-1 flex flex-wrap items-center gap-1 text-[11px] text-imp-muted-foreground\">\n <span>Root</span>\n {scopePath.map((team) => (\n <div key={team.id} className=\"flex items-center gap-1\">\n <ChevronRight className=\"w-3 h-3\" />\n <span>{team.name}</span>\n </div>\n ))}\n <div className=\"flex items-center gap-1\">\n <ChevronRight className=\"w-3 h-3\" />\n <span className=\"font-medium text-imp-foreground\">{flowName}</span>\n </div>\n </div>\n </div>\n <div className=\"flex items-center gap-1.5\">\n <button\n type=\"button\"\n onClick={openFlow}\n className=\"flex items-center gap-1.5 rounded-md border border-imp-border px-3 py-1.5 text-xs font-medium text-imp-muted-foreground transition-colors hover:border-imp-primary/50 hover:text-imp-foreground\"\n >\n <ExternalLink className=\"w-4 h-4\" /> Open in Editor\n </button>\n </div>\n </div>\n <p className=\"mt-3 text-xs text-imp-muted-foreground\">\n All principals with access and how they got it.\n </p>\n </div>\n\n <div className=\"flex-1 px-5 py-4 overflow-x-hidden overflow-y-auto\">\n <div className=\"space-y-6\">\n <section className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"text-sm font-semibold text-imp-foreground\">Direct Access</h3>\n {isAdmin ? (\n <button\n type=\"button\"\n onClick={() => setShowGrantDialog(true)}\n className=\"flex items-center gap-1.5 rounded-md border border-imp-border px-3 py-1.5 text-xs font-medium text-imp-muted-foreground transition-colors hover:border-imp-primary/50 hover:text-imp-foreground\"\n >\n <Plus className=\"w-4 h-4\" /> Grant Access\n </button>\n ) : null}\n </div>\n <div className=\"overflow-hidden border rounded-xl border-imp-border bg-imp-background/40\">\n <AccessTable\n rows={directRows}\n isLoading={effectiveFlowAccessQuery.isLoading}\n emptyLabel=\"No direct access assigned\"\n />\n </div>\n </section>\n\n <section className=\"space-y-2\">\n <h3 className=\"text-sm font-semibold text-imp-foreground\">Inherited Access</h3>\n <div className=\"overflow-hidden border rounded-xl border-imp-border bg-imp-background/40\">\n <AccessTable\n rows={inheritedRows}\n isLoading={effectiveFlowAccessQuery.isLoading}\n emptyLabel=\"No inherited access\"\n />\n </div>\n </section>\n </div>\n </div>\n\n <FormDialog\n open={showGrantDialog}\n onClose={() => setShowGrantDialog(false)}\n title=\"Grant Flow Access\"\n >\n <div className=\"flex flex-col gap-3\">\n <PrincipalCombobox\n users={users}\n teams={teams}\n excludeUserIds={existingDirectUserIds}\n excludeTeamIds={existingDirectTeamIds}\n selections={principalSelections}\n onSelect={setPrincipalSelections}\n />\n <div className=\"flex items-center gap-2\">\n <RoleSelector value={permission} onChange={setPermission} />\n <button\n type=\"button\"\n onClick={() => {\n if (principalSelections.length === 0) {\n return;\n }\n for (const sel of principalSelections) {\n grantFlowAccess.mutate({\n ...(sel.type === 'user' ? { userId: sel.id } : { teamId: sel.id }),\n permission,\n });\n }\n setPrincipalSelections([]);\n setShowGrantDialog(false);\n }}\n disabled={principalSelections.length === 0 || grantFlowAccess.isPending}\n className=\"ml-auto rounded-md bg-imp-primary px-4 py-2 text-sm font-semibold text-imp-primary-foreground hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n Grant\n </button>\n </div>\n </div>\n </FormDialog>\n </div>\n );\n}\n","import { Move, User, Users, X } from 'lucide-react';\nimport { useMoveFlow } from '../../hooks/useScopes';\nimport { useUpdateTeam } from '../../hooks/useTeams';\nimport type { MovePreviewResponse } from '../../../shared/types';\nimport type { PendingMove } from './types';\nimport { getPermissionBadgeClasses } from './types';\n\nexport function MoveConfirmationDialog({\n pendingMove,\n preview,\n error,\n onClose,\n}: {\n pendingMove: PendingMove | null;\n preview: MovePreviewResponse | null;\n error: string | null;\n onClose: () => void;\n}) {\n const moveFlow = useMoveFlow(pendingMove?.type === 'flow' ? pendingMove.id : '');\n const reparentScope = useUpdateTeam(pendingMove?.type === 'scope' ? pendingMove.id : '');\n\n const isSubmitting = moveFlow.isPending || reparentScope.isPending;\n\n const handleConfirm = async () => {\n if (!pendingMove) {\n return;\n }\n if (pendingMove.type === 'flow') {\n await moveFlow.mutateAsync(pendingMove.targetScopeId);\n } else {\n await reparentScope.mutateAsync({ parentId: pendingMove.targetScopeId });\n }\n onClose();\n };\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/35\">\n <div className=\"w-full max-w-lg rounded-xl border border-imp-border bg-imp-background shadow-[var(--imp-shadow-floating)]\">\n <div className=\"flex items-center justify-between px-5 py-4 border-b border-imp-border\">\n <div>\n <div className=\"flex items-center gap-2 text-sm font-semibold text-imp-foreground\">\n <Move className=\"w-4 h-4 text-imp-primary\" />\n Confirm Move\n </div>\n <p className=\"mt-1 text-xs text-imp-muted-foreground\">\n Review the access impact before applying this hierarchy change.\n </p>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1 rounded text-imp-muted-foreground hover:text-imp-foreground\"\n >\n <X className=\"w-4 h-4\" />\n </button>\n </div>\n\n <div className=\"px-5 py-4 space-y-4 text-sm\">\n {error ? (\n <div className=\"px-3 py-2 text-red-700 border border-red-300 rounded-lg bg-red-50 dark:border-red-900 dark:bg-red-950/20 dark:text-red-300\">\n {error}\n </div>\n ) : !preview ? (\n <div className=\"px-3 py-4 text-center border rounded-lg border-imp-border bg-imp-card text-imp-muted-foreground\">\n Calculating impact…\n </div>\n ) : (\n <>\n <div className=\"px-3 py-3 border rounded-lg border-imp-border bg-imp-card\">\n <div className=\"font-medium text-imp-foreground\">\n Move \"{preview.item.name}\" to{' '}\n {preview.target.path.length > 0 ? preview.target.path.join(' / ') : 'Top level'}\n </div>\n <div className=\"mt-1 text-xs text-imp-muted-foreground\">\n {preview.affectedFlows} flow{preview.affectedFlows === 1 ? '' : 's'} affected\n </div>\n </div>\n\n <div>\n <div className=\"mb-2 text-xs font-medium tracking-wider uppercase text-imp-muted-foreground\">\n Access Changes\n </div>\n <div className=\"p-2 space-y-1 overflow-y-auto border rounded-lg max-h-56 border-imp-border bg-imp-card\">\n {preview.accessChanges.gained.length === 0 ? (\n <div className=\"px-2 py-2 text-xs text-imp-muted-foreground\">\n No new principals gain access from this move.\n </div>\n ) : (\n preview.accessChanges.gained.map((entry) => (\n <div\n key={`${entry.source}-${entry.name}`}\n className=\"flex items-center gap-2 rounded-md px-2 py-1.5 text-xs\"\n >\n <div className=\"flex items-center justify-center w-6 h-6 rounded-full shrink-0 bg-imp-primary/10\">\n {entry.userId ? (\n <User className=\"w-3 h-3 text-imp-primary\" />\n ) : (\n <Users className=\"w-3 h-3 text-imp-primary\" />\n )}\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"font-medium truncate\">{entry.name}</div>\n <div className=\"truncate text-[10px] text-imp-muted-foreground\">\n {entry.source}\n </div>\n </div>\n <span\n className={`rounded px-1.5 py-0.5 text-[10px] font-medium ${getPermissionBadgeClasses(entry.permission)}`}\n >\n {entry.permission}\n </span>\n </div>\n ))\n )}\n </div>\n <p className=\"mt-2 text-xs text-imp-muted-foreground\">\n {preview.accessChanges.unchanged} access grant\n {preview.accessChanges.unchanged === 1 ? '' : 's'} remain unchanged.\n </p>\n </div>\n </>\n )}\n </div>\n\n <div className=\"flex items-center justify-end gap-2 px-5 py-4 border-t border-imp-border\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"rounded border border-imp-border px-3 py-1.5 text-sm text-imp-muted-foreground hover:text-imp-foreground\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={handleConfirm}\n disabled={!preview || isSubmitting || !!error}\n className=\"rounded bg-imp-primary px-3 py-1.5 text-sm font-medium text-imp-primary-foreground hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n {isSubmitting ? 'Applying…' : `Move ${pendingMove?.type === 'scope' ? 'Team' : 'Flow'}`}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","import { create } from 'zustand';\nimport type { MovePreviewResponse, ScopeTreeNode } from '../../shared/types';\nimport type { PendingMove, SelectedItem } from '../components/access-control/types';\n\nexport type HierarchyDragItem = {\n type: 'scope' | 'flow';\n id: string;\n name: string;\n /** Current parent scope id, or null if at root */\n parentId: string | null;\n};\n\ninterface AccessControlState {\n // Selection\n selected: SelectedItem | null;\n setSelected: (item: SelectedItem | null) => void;\n\n // Tree\n expandedNodes: Set<string>;\n setExpandedNodes: (nodes: Set<string>) => void;\n toggleNode: (scopeId: string) => void;\n expandAll: (ids: string[]) => void;\n\n // Search\n search: string;\n setSearch: (q: string) => void;\n\n // New team creation\n showNewTeam: boolean;\n setShowNewTeam: (show: boolean) => void;\n newTeamName: string;\n setNewTeamName: (name: string) => void;\n\n // Drag-and-drop\n draggedItem: HierarchyDragItem | null;\n dropTarget: string | null; // scope id or 'root', null when nothing hovered\n startDrag: (item: HierarchyDragItem) => void;\n endDrag: () => void;\n /**\n * Called on dragover for a specific target.\n * Returns true if the drop is valid (caller should call event.preventDefault).\n */\n setDropTarget: (targetId: string | null) => void;\n\n // Move flow\n pendingMove: PendingMove | null;\n movePreview: MovePreviewResponse | null;\n moveError: string | null;\n setPendingMove: (move: PendingMove | null) => void;\n setMovePreview: (preview: MovePreviewResponse | null) => void;\n setMoveError: (error: string | null) => void;\n clearMove: () => void;\n}\n\nexport const useAccessControlStore = create<AccessControlState>()((set) => ({\n // Selection\n selected: null,\n setSelected: (item) => set({ selected: item }),\n\n // Tree\n expandedNodes: new Set(),\n setExpandedNodes: (nodes) => set({ expandedNodes: nodes }),\n toggleNode: (scopeId) =>\n set((state) => {\n const next = new Set(state.expandedNodes);\n if (next.has(scopeId)) {\n next.delete(scopeId);\n } else {\n next.add(scopeId);\n }\n return { expandedNodes: next };\n }),\n expandAll: (ids) => set({ expandedNodes: new Set(ids) }),\n\n // Search\n search: '',\n setSearch: (q) => set({ search: q }),\n\n // New team\n showNewTeam: false,\n setShowNewTeam: (show) => set({ showNewTeam: show }),\n newTeamName: '',\n setNewTeamName: (name) => set({ newTeamName: name }),\n\n // Drag-and-drop\n draggedItem: null,\n dropTarget: null,\n startDrag: (item) => set({ draggedItem: item, dropTarget: null }),\n endDrag: () => set({ draggedItem: null, dropTarget: null }),\n setDropTarget: (targetId) => set({ dropTarget: targetId }),\n\n // Move\n pendingMove: null,\n movePreview: null,\n moveError: null,\n setPendingMove: (move) => set({ pendingMove: move }),\n setMovePreview: (preview) => set({ movePreview: preview }),\n setMoveError: (error) => set({ moveError: error }),\n clearMove: () => set({ pendingMove: null, movePreview: null, moveError: null }),\n}));\n\n// ─── Drag-and-drop helpers ───────────────────────────────────────────────────\n\nfunction collectScopeIds(scopes: ScopeTreeNode[]): string[] {\n return scopes.flatMap((scope) => [scope.id, ...collectScopeIds(scope.children)]);\n}\n\nfunction findScopeNode(scopes: ScopeTreeNode[], scopeId: string): ScopeTreeNode | null {\n for (const scope of scopes) {\n if (scope.id === scopeId) {\n return scope;\n }\n const child = findScopeNode(scope.children, scopeId);\n if (child) {\n return child;\n }\n }\n return null;\n}\n\nfunction scopeContains(scope: ScopeTreeNode, potentialChildId: string): boolean {\n for (const child of scope.children) {\n if (child.id === potentialChildId || scopeContains(child, potentialChildId)) {\n return true;\n }\n }\n return false;\n}\n\nexport function isDescendantScope(\n scopes: ScopeTreeNode[],\n draggedScopeId: string,\n potentialTargetId: string,\n): boolean {\n const draggedScope = findScopeNode(scopes, draggedScopeId);\n if (!draggedScope) {\n return false;\n }\n return scopeContains(draggedScope, potentialTargetId);\n}\n\nexport { collectScopeIds };\n\n/**\n * Returns true if dropping `dragged` onto `targetId` is a valid move.\n * targetId of null means \"move to root\".\n */\nexport function canDropOnTarget(\n dragged: HierarchyDragItem,\n targetId: string | null,\n allScopes: ScopeTreeNode[],\n): boolean {\n // Can't drop a scope onto itself\n if (dragged.type === 'scope' && dragged.id === targetId) {\n return false;\n }\n // Can't drop a scope onto one of its own descendants\n if (\n dragged.type === 'scope' &&\n targetId !== null &&\n isDescendantScope(allScopes, dragged.id, targetId)\n ) {\n return false;\n }\n // No-op: item is already in this scope\n if (dragged.parentId === targetId) {\n return false;\n }\n return true;\n}\n","import { useCallback, useEffect, useMemo } from 'react';\nimport { clsx } from 'clsx';\nimport {\n ChevronDown,\n ChevronRight,\n FolderInput,\n GripVertical,\n Plus,\n Search,\n Shield,\n Users,\n Workflow,\n} from 'lucide-react';\nimport { PageLayout } from '@invect/frontend';\nimport { useRbac } from '../../providers/RbacProvider';\nimport { useTeams, useCreateTeam } from '../../hooks/useTeams';\nimport { useScopeTree, usePreviewMove } from '../../hooks/useScopes';\nimport type { FlowSummary, ScopeTreeNode } from '../../../shared/types';\nimport type { AuthUser, SelectedItem } from './types';\nimport { formatPermissionLabel, getPermissionBadgeClasses } from './types';\nimport { useUsers } from './useUsers';\nimport { ScopeDetailPanel } from './ScopeDetailPanel';\nimport { FlowDetailPanel } from './FlowDetailPanel';\nimport { MoveConfirmationDialog } from './MoveConfirmationDialog';\nimport {\n useAccessControlStore,\n canDropOnTarget,\n collectScopeIds,\n type HierarchyDragItem,\n} from '../../stores/accessControlStore';\n\n// ─── Tree helpers ─────────────────────────────────────────────────────────────\n\nfunction findScopeNode(scopes: ScopeTreeNode[], scopeId: string): ScopeTreeNode | null {\n for (const scope of scopes) {\n if (scope.id === scopeId) {\n return scope;\n }\n const child = findScopeNode(scope.children, scopeId);\n if (child) {\n return child;\n }\n }\n return null;\n}\n\nfunction filterScopes(scopes: ScopeTreeNode[], query: string): ScopeTreeNode[] {\n return scopes.reduce<ScopeTreeNode[]>((acc, scope) => {\n const matchesScope =\n scope.name.toLowerCase().includes(query) ||\n (scope.description?.toLowerCase().includes(query) ?? false);\n const matchingChildren = filterScopes(scope.children, query);\n const matchingFlows = scope.flows.filter((flow) => flow.name.toLowerCase().includes(query));\n\n if (matchesScope || matchingChildren.length > 0 || matchingFlows.length > 0) {\n acc.push({ ...scope, children: matchingChildren, flows: matchingFlows });\n }\n return acc;\n }, []);\n}\n\nfunction findSelectedName(\n scopes: ScopeTreeNode[],\n flows: FlowSummary[],\n selected: SelectedItem | null,\n): string | null {\n if (!selected) {\n return null;\n }\n\n if (selected.kind === 'team') {\n return findScopeNode(scopes, selected.id)?.name ?? selected.name;\n }\n\n const stack = [...flows];\n const scopeStack = [...scopes];\n while (scopeStack.length > 0) {\n const current = scopeStack.pop();\n if (!current) {\n break;\n }\n stack.push(...current.flows);\n scopeStack.push(...current.children);\n }\n return stack.find((flow) => flow.id === selected.id)?.name ?? selected.name;\n}\n\n// ─── FlowTreeRow ──────────────────────────────────────────────────────────────\n\nfunction FlowTreeRow({\n flow,\n isSelected,\n onSelect,\n}: {\n flow: FlowSummary;\n isSelected: boolean;\n onSelect: (flow: FlowSummary) => void;\n}) {\n const { draggedItem, startDrag, endDrag } = useAccessControlStore();\n const isDragging = draggedItem?.type === 'flow' && draggedItem.id === flow.id;\n\n return (\n <div\n draggable\n onDragStart={(event) => {\n event.dataTransfer.effectAllowed = 'move';\n startDrag({ type: 'flow', id: flow.id, name: flow.name, parentId: flow.scopeId ?? null });\n }}\n onDragEnd={endDrag}\n onClick={() => onSelect(flow)}\n className={clsx(\n 'group flex cursor-pointer items-center gap-2 rounded-md px-4 py-1.5 transition-colors',\n 'hover:bg-imp-muted/50',\n isDragging && 'opacity-40',\n isSelected && 'bg-imp-primary/10 text-imp-primary ring-1 ring-imp-primary/30',\n )}\n >\n <Workflow\n className={clsx(\n 'h-4 w-4 shrink-0',\n isSelected ? 'text-imp-primary' : 'text-imp-muted-foreground',\n )}\n />\n <span className=\"flex-1 min-w-0 text-sm font-medium truncate\">{flow.name}</span>\n <GripVertical className=\"h-3.5 w-3.5 shrink-0 text-imp-muted-foreground/60 opacity-0 transition-opacity group-hover:opacity-100\" />\n </div>\n );\n}\n\n// ─── ScopeTreeRow ─────────────────────────────────────────────────────────────\n\nfunction ScopeTreeRow({\n scope,\n allScopes,\n depth,\n onSelectScope,\n onSelectFlow,\n onTriggerMove,\n}: {\n scope: ScopeTreeNode;\n allScopes: ScopeTreeNode[];\n depth: number;\n onSelectScope: (scope: ScopeTreeNode) => void;\n onSelectFlow: (flow: FlowSummary) => void;\n onTriggerMove: (item: HierarchyDragItem, targetId: string | null) => void;\n}) {\n const {\n draggedItem,\n dropTarget,\n selected,\n expandedNodes,\n startDrag,\n endDrag,\n setDropTarget,\n toggleNode,\n } = useAccessControlStore();\n\n const isExpanded = expandedNodes.has(scope.id);\n const isSelected = selected?.kind === 'team' && selected.id === scope.id;\n const isDragging = draggedItem?.type === 'scope' && draggedItem.id === scope.id;\n const hasChildren = scope.children.length > 0 || scope.flows.length > 0;\n\n const canDrop = draggedItem !== null && canDropOnTarget(draggedItem, scope.id, allScopes);\n const isDropTarget = dropTarget === scope.id && canDrop;\n\n const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {\n if (!draggedItem || !canDrop) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n if (dropTarget !== scope.id) {\n setDropTarget(scope.id);\n }\n };\n\n // Use relatedTarget to avoid clearing the drop highlight when entering a child node.\n const handleDragLeave = (event: React.DragEvent<HTMLDivElement>) => {\n const related = event.relatedTarget as Node | null;\n if (related && event.currentTarget.contains(related)) {\n return;\n }\n if (dropTarget === scope.id) {\n setDropTarget(null);\n }\n };\n\n const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n event.stopPropagation();\n if (!draggedItem || !canDrop) {\n return;\n }\n onTriggerMove(draggedItem, scope.id);\n };\n\n return (\n <div onDragOver={handleDragOver} onDragLeave={handleDragLeave} onDrop={handleDrop}>\n <div\n draggable\n onDragStart={(event) => {\n event.dataTransfer.effectAllowed = 'move';\n startDrag({\n type: 'scope',\n id: scope.id,\n name: scope.name,\n parentId: scope.parentId ?? null,\n });\n }}\n onDragEnd={endDrag}\n onClick={() => onSelectScope(scope)}\n className={clsx(\n 'group flex cursor-pointer items-center gap-2 rounded-xl px-3 py-2 transition-colors',\n isDragging && 'opacity-40',\n isDropTarget && 'ring-2 ring-imp-primary/40 bg-imp-primary/5',\n isSelected ? 'text-imp-primary ring-1 ring-imp-primary/30' : 'hover:bg-accent',\n )}\n >\n {hasChildren ? (\n <button\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n toggleNode(scope.id);\n }}\n className=\"rounded p-0.5 text-imp-muted-foreground hover:bg-imp-muted\"\n >\n {isExpanded ? (\n <ChevronDown className=\"w-4 h-4\" />\n ) : (\n <ChevronRight className=\"w-4 h-4\" />\n )}\n </button>\n ) : (\n <span className=\"w-5 shrink-0\" />\n )}\n <Users\n className={clsx(\n 'h-4 w-4 shrink-0',\n isSelected ? 'text-imp-primary' : 'text-imp-muted-foreground',\n )}\n />\n <span className=\"flex-1 min-w-0 text-sm font-medium truncate\">{scope.name}</span>\n {scope.teamPermission ? (\n <span\n className={clsx(\n 'inline-flex shrink-0 rounded-full border px-2 py-0.5 text-[10px] font-medium',\n getPermissionBadgeClasses(scope.teamPermission),\n )}\n >\n {formatPermissionLabel(scope.teamPermission)}\n </span>\n ) : null}\n <GripVertical className=\"h-3.5 w-3.5 shrink-0 text-imp-muted-foreground/60 opacity-0 transition-opacity group-hover:opacity-100\" />\n </div>\n\n {isExpanded ? (\n <div className=\"space-y-1 border-l border-imp-border\" style={{ marginLeft: '22px' }}>\n {scope.flows.map((flow) => (\n <FlowTreeRow\n key={flow.id}\n flow={flow}\n isSelected={selected?.kind === 'flow' && selected.id === flow.id}\n onSelect={onSelectFlow}\n />\n ))}\n {scope.children.map((child) => (\n <ScopeTreeRow\n key={child.id}\n scope={child}\n allScopes={allScopes}\n depth={depth + 1}\n onSelectScope={onSelectScope}\n onSelectFlow={onSelectFlow}\n onTriggerMove={onTriggerMove}\n />\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n\nconst EMPTY_SCOPES: ScopeTreeNode[] = [];\nconst EMPTY_FLOWS: FlowSummary[] = [];\n\nexport function AccessControlPage() {\n const { isAuthenticated, checkPermission } = useRbac();\n const isAdmin = isAuthenticated && checkPermission('admin:*');\n\n const users = useUsers();\n const userMap = useMemo(() => {\n const map = new Map<string, AuthUser>();\n for (const user of users) {\n map.set(user.id, user);\n }\n return map;\n }, [users]);\n\n const teamsQuery = useTeams();\n const teams = teamsQuery.data?.teams ?? [];\n const scopeTreeQuery = useScopeTree();\n const createTeam = useCreateTeam();\n const previewMove = usePreviewMove();\n\n const {\n selected,\n setSelected,\n search,\n setSearch,\n expandedNodes,\n expandAll,\n showNewTeam,\n setShowNewTeam,\n newTeamName,\n setNewTeamName,\n draggedItem,\n dropTarget,\n setDropTarget,\n endDrag,\n pendingMove,\n setPendingMove,\n movePreview,\n setMovePreview,\n moveError,\n setMoveError,\n clearMove,\n } = useAccessControlStore();\n\n const scopes = scopeTreeQuery.data?.scopes ?? EMPTY_SCOPES;\n const unscopedFlows = scopeTreeQuery.data?.unscopedFlows ?? EMPTY_FLOWS;\n\n // Auto-expand everything when tree first loads\n useEffect(() => {\n if (scopes.length > 0 && expandedNodes.size === 0) {\n expandAll(collectScopeIds(scopes));\n }\n }, [scopes]); // expanding on load — intentionally tracks scopes only\n\n useEffect(() => {\n scopeTreeQuery.refetch();\n }, []); // fires once on mount\n\n const normalizedSearch = search.trim().toLowerCase();\n const filteredScopes = useMemo(\n () => (normalizedSearch ? filterScopes(scopes, normalizedSearch) : scopes),\n [scopes, normalizedSearch],\n );\n const filteredUnscopedFlows = useMemo(\n () =>\n normalizedSearch\n ? unscopedFlows.filter((f) => f.name.toLowerCase().includes(normalizedSearch))\n : unscopedFlows,\n [unscopedFlows, normalizedSearch],\n );\n\n const selectedName = useMemo(\n () => findSelectedName(scopes, unscopedFlows, selected),\n [scopes, unscopedFlows, selected],\n );\n\n const hasTreeItems = filteredScopes.length > 0 || filteredUnscopedFlows.length > 0;\n\n // Called when a valid drop lands on a target scope (or null = root)\n const handleTriggerMove = useCallback(\n async (item: HierarchyDragItem, targetScopeId: string | null) => {\n endDrag();\n\n if (!canDropOnTarget(item, targetScopeId, scopes)) {\n return;\n }\n\n setPendingMove({ type: item.type, id: item.id, name: item.name, targetScopeId });\n setMovePreview(null);\n setMoveError(null);\n\n try {\n const preview = await previewMove.mutateAsync({\n type: item.type,\n id: item.id,\n targetScopeId,\n });\n setMovePreview(preview);\n } catch (err) {\n setMoveError(err instanceof Error ? err.message : 'Failed to preview move');\n }\n },\n [scopes, endDrag, previewMove, setPendingMove, setMovePreview, setMoveError],\n );\n\n if (!isAuthenticated) {\n return (\n <PageLayout\n title=\"Access Control\"\n subtitle=\"Manage team hierarchy and flow-level access grants.\"\n icon={Shield}\n >\n <p className=\"text-sm text-imp-muted-foreground\">Please sign in to access this page.</p>\n </PageLayout>\n );\n }\n\n const isLoading = scopeTreeQuery.isLoading;\n\n return (\n <PageLayout\n title=\"Access Control\"\n subtitle=\"Manage team hierarchy and flow-level access grants.\"\n icon={Shield}\n >\n {/* Search + New Team */}\n <div className=\"flex items-center gap-2\">\n <div className=\"relative flex-1 max-w-sm\">\n <Search className=\"absolute w-3.5 h-3.5 pointer-events-none left-3 top-1/2 -translate-y-1/2 text-imp-muted-foreground\" />\n <input\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n placeholder=\"Search teams and flows…\"\n className=\"w-full py-2 pr-3 text-sm border rounded-lg outline-none pl-9 border-imp-border bg-imp-background placeholder:text-imp-muted-foreground focus:border-imp-primary/50\"\n />\n </div>\n {isAdmin ? (\n showNewTeam ? (\n <div className=\"flex items-center gap-1.5\">\n <input\n value={newTeamName}\n onChange={(event) => setNewTeamName(event.target.value)}\n placeholder=\"Team name\"\n className=\"px-2.5 py-2 text-sm border rounded-lg border-imp-border bg-imp-background\"\n autoFocus\n onKeyDown={(event) => {\n if (event.key === 'Enter' && newTeamName.trim()) {\n createTeam.mutate({ name: newTeamName.trim() });\n setNewTeamName('');\n setShowNewTeam(false);\n }\n if (event.key === 'Escape') {\n setShowNewTeam(false);\n setNewTeamName('');\n }\n }}\n />\n <button\n type=\"button\"\n onClick={() => {\n if (!newTeamName.trim()) {\n return;\n }\n createTeam.mutate({ name: newTeamName.trim() });\n setNewTeamName('');\n setShowNewTeam(false);\n }}\n disabled={!newTeamName.trim()}\n className=\"px-3 py-2 text-sm font-medium rounded-lg bg-imp-primary text-imp-primary-foreground hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n Create\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setShowNewTeam(false);\n setNewTeamName('');\n }}\n className=\"px-3 py-2 text-sm rounded-lg text-imp-muted-foreground hover:text-imp-foreground\"\n >\n Cancel\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => setShowNewTeam(true)}\n className=\"flex items-center gap-1.5 rounded-lg border border-imp-border px-3 py-2 text-sm font-medium text-imp-muted-foreground hover:border-imp-primary/50 hover:text-imp-foreground\"\n >\n <Plus className=\"w-4 h-4\" /> New Team\n </button>\n )\n ) : null}\n </div>\n\n {/* Two-pane layout */}\n <div\n className=\"grid h-[calc(100vh-220px)] min-h-130 border rounded-lg overflow-hidden\"\n style={{ gridTemplateColumns: '320px 1fr' }}\n >\n {/* Left: hierarchy tree */}\n <div className=\"flex flex-col overflow-hidden bg-imp-muted/20\">\n <div\n className=\"flex-1 px-1 py-2 overflow-y-auto\"\n onDragOver={(event) => {\n if (!draggedItem) {\n return;\n }\n // Root-level drop zone: only activate when not over a child scope row\n if (dropTarget === null) {\n event.preventDefault();\n setDropTarget('root');\n }\n }}\n onDragLeave={(event) => {\n const related = event.relatedTarget as Node | null;\n if (related && event.currentTarget.contains(related)) {\n return;\n }\n if (dropTarget === 'root') {\n setDropTarget(null);\n }\n }}\n onDrop={(event) => {\n event.preventDefault();\n if (!draggedItem) {\n return;\n }\n handleTriggerMove(draggedItem, null);\n }}\n >\n <div\n className={clsx(\n 'min-h-full rounded-lg py-1 transition-colors',\n dropTarget === 'root'\n ? 'bg-imp-primary/5 ring-1 ring-imp-primary/20 ring-inset'\n : '',\n )}\n >\n {isLoading ? (\n <div className=\"flex items-center justify-center px-4 py-12 text-sm text-center text-imp-muted-foreground\">\n Loading hierarchy…\n </div>\n ) : !hasTreeItems ? (\n <div className=\"flex flex-col items-center justify-center px-6 py-16 text-center\">\n <FolderInput className=\"w-10 h-10 mb-3 opacity-30 text-imp-muted-foreground\" />\n <h3 className=\"text-base font-medium text-imp-foreground\">\n {normalizedSearch ? 'No matching teams or flows' : 'No teams or flows yet'}\n </h3>\n <p className=\"max-w-sm mt-2 text-sm text-imp-muted-foreground\">\n {normalizedSearch\n ? 'Adjust the search to find a team or flow in the hierarchy.'\n : 'Create a team to start organizing flows and access scopes.'}\n </p>\n </div>\n ) : (\n <div className=\"space-y-1\">\n {filteredUnscopedFlows.map((flow) => (\n <FlowTreeRow\n key={flow.id}\n flow={flow}\n isSelected={selected?.kind === 'flow' && selected.id === flow.id}\n onSelect={(nextFlow) =>\n setSelected({ kind: 'flow', id: nextFlow.id, name: nextFlow.name })\n }\n />\n ))}\n\n {filteredScopes.map((scope) => (\n <ScopeTreeRow\n key={scope.id}\n scope={scope}\n allScopes={scopes}\n depth={0}\n onSelectScope={(nextScope) =>\n setSelected({ kind: 'team', id: nextScope.id, name: nextScope.name })\n }\n onSelectFlow={(nextFlow) =>\n setSelected({ kind: 'flow', id: nextFlow.id, name: nextFlow.name })\n }\n onTriggerMove={handleTriggerMove}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Right: detail panel */}\n <aside className=\"flex flex-col overflow-hidden border-l border-imp-border bg-imp-muted/30\">\n {!selected ? (\n <div className=\"flex flex-col items-center justify-center h-full gap-4 px-8 text-center text-imp-muted-foreground\">\n <div className=\"flex items-center justify-center w-12 h-12 rounded-xl bg-imp-primary/5\">\n <Shield className=\"w-6 h-6 text-imp-primary/40\" />\n </div>\n <div>\n <p className=\"text-sm font-medium text-imp-foreground\">Select a team or flow</p>\n <p className=\"mt-1.5 text-xs text-imp-muted-foreground max-w-[280px]\">\n Choose an item from the tree to manage its members and permissions.\n </p>\n </div>\n {hasTreeItems ? null : isAdmin ? (\n <button\n type=\"button\"\n onClick={() => setShowNewTeam(true)}\n className=\"flex items-center gap-1.5 rounded-lg border border-imp-border px-3 py-1.5 text-xs font-medium text-imp-foreground transition-colors hover:border-imp-primary/50 hover:bg-imp-muted/50\"\n >\n <Plus className=\"h-3.5 w-3.5\" /> Create your first team\n </button>\n ) : null}\n </div>\n ) : selected.kind === 'team' ? (\n <ScopeDetailPanel\n scopeId={selected.id}\n scopeName={selectedName ?? selected.name}\n users={users}\n userMap={userMap}\n teams={teams}\n isAdmin={!!isAdmin}\n />\n ) : (\n <FlowDetailPanel\n flowId={selected.id}\n flowName={selectedName ?? selected.name}\n users={users}\n userMap={userMap}\n teams={teams}\n isAdmin={!!isAdmin}\n />\n )}\n </aside>\n </div>\n\n {pendingMove ? (\n <MoveConfirmationDialog\n pendingMove={pendingMove}\n preview={movePreview}\n error={moveError}\n onClose={clearMove}\n />\n ) : null}\n </PageLayout>\n );\n}\n","/**\n * TeamsPage — Team management page with create/edit/delete teams and member management.\n */\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { ChevronDown, ChevronRight, Plus, Search, Trash2, User, Users, X } from 'lucide-react';\nimport { useApiClient, PageLayout } from '@invect/frontend';\nimport { useRbac } from '../providers/RbacProvider';\nimport {\n useTeams,\n useTeam,\n useCreateTeam,\n useDeleteTeam,\n useAddTeamMember,\n useRemoveTeamMember,\n} from '../hooks/useTeams';\n\n// ─────────────────────────────────────────────────────────────\n// User fetching (reused from AccessControlPage pattern)\n// ─────────────────────────────────────────────────────────────\n\ninterface AuthUser {\n id: string;\n name?: string;\n email?: string;\n}\n\nfunction useUsers() {\n const api = useApiClient();\n const [users, setUsers] = useState<AuthUser[]>([]);\n\n useEffect(() => {\n let cancelled = false;\n fetch(`${api.getBaseURL()}/plugins/auth/users?limit=200`, { credentials: 'include' })\n .then((r) => (r.ok ? r.json() : null))\n .then((data) => {\n if (!cancelled && data?.users) {\n setUsers(data.users);\n }\n })\n .catch(() => {});\n return () => {\n cancelled = true;\n };\n }, [api]);\n\n return { users };\n}\n\n// ─────────────────────────────────────────────────────────────\n// Main Page\n// ─────────────────────────────────────────────────────────────\n\nexport function TeamsPage() {\n const { isAuthenticated, checkPermission } = useRbac();\n const teamsQuery = useTeams();\n const createTeam = useCreateTeam();\n const deleteTeam = useDeleteTeam();\n const { users } = useUsers();\n\n const [expandedTeamId, setExpandedTeamId] = useState<string | null>(null);\n const [teamSearch, setTeamSearch] = useState('');\n const [showCreateForm, setShowCreateForm] = useState(false);\n const [newTeamName, setNewTeamName] = useState('');\n const [newTeamDescription, setNewTeamDescription] = useState('');\n\n const teams = teamsQuery.data?.teams ?? [];\n const isAdmin = isAuthenticated && checkPermission('admin:*');\n\n const userMap = useMemo(() => {\n const map = new Map<string, AuthUser>();\n for (const u of users) {\n map.set(u.id, u);\n }\n return map;\n }, [users]);\n\n const filteredTeams = useMemo(() => {\n const q = teamSearch.trim().toLowerCase();\n if (!q) {\n return teams;\n }\n return teams.filter(\n (t) => t.name.toLowerCase().includes(q) || t.description?.toLowerCase().includes(q),\n );\n }, [teams, teamSearch]);\n\n const handleCreate = async () => {\n if (!newTeamName.trim()) {\n return;\n }\n await createTeam.mutateAsync({\n name: newTeamName.trim(),\n description: newTeamDescription.trim() || undefined,\n });\n setNewTeamName('');\n setNewTeamDescription('');\n setShowCreateForm(false);\n };\n\n const handleDelete = async (teamId: string) => {\n await deleteTeam.mutateAsync(teamId);\n if (expandedTeamId === teamId) {\n setExpandedTeamId(null);\n }\n };\n\n if (!isAuthenticated) {\n return (\n <div className=\"flex items-center justify-center w-full h-full min-h-0 overflow-y-auto imp-page bg-imp-background text-imp-foreground\">\n <p className=\"text-sm text-imp-muted-foreground\">Please sign in to access this page.</p>\n </div>\n );\n }\n\n return (\n <PageLayout\n title=\"Teams\"\n icon={Users}\n actions={\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-imp-muted-foreground\">\n {filteredTeams.length} team{filteredTeams.length !== 1 ? 's' : ''}\n </span>\n {isAdmin && (\n <button\n type=\"button\"\n onClick={() => setShowCreateForm(!showCreateForm)}\n className=\"flex items-center gap-1 px-2 py-1 text-xs font-medium rounded bg-imp-primary text-imp-primary-foreground hover:bg-imp-primary/90\"\n >\n <Plus className=\"w-3 h-3\" />\n New Team\n </button>\n )}\n </div>\n }\n >\n {/* Create team form */}\n {showCreateForm && (\n <div className=\"p-3 border rounded-lg border-imp-border bg-imp-card\">\n <div className=\"mb-2 text-xs font-medium text-imp-foreground\">Create Team</div>\n <div className=\"space-y-2\">\n <input\n type=\"text\"\n value={newTeamName}\n onChange={(e) => setNewTeamName(e.target.value)}\n placeholder=\"Team name\"\n className=\"w-full rounded border border-imp-border bg-imp-background px-2 py-1.5 text-sm placeholder:text-imp-muted-foreground\"\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n handleCreate();\n }\n }}\n />\n <input\n type=\"text\"\n value={newTeamDescription}\n onChange={(e) => setNewTeamDescription(e.target.value)}\n placeholder=\"Description (optional)\"\n className=\"w-full rounded border border-imp-border bg-imp-background px-2 py-1.5 text-sm placeholder:text-imp-muted-foreground\"\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n handleCreate();\n }\n }}\n />\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleCreate}\n disabled={createTeam.isPending || !newTeamName.trim()}\n className=\"px-3 py-1 text-xs font-medium rounded bg-imp-primary text-imp-primary-foreground hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n {createTeam.isPending ? 'Creating…' : 'Create'}\n </button>\n <button\n type=\"button\"\n onClick={() => setShowCreateForm(false)}\n className=\"px-3 py-1 text-xs rounded text-imp-muted-foreground hover:text-imp-foreground\"\n >\n Cancel\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Search */}\n <div className=\"relative\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-imp-muted-foreground\" />\n <input\n value={teamSearch}\n onChange={(e) => setTeamSearch(e.target.value)}\n placeholder=\"Search teams…\"\n className=\"w-full rounded-lg border border-imp-border bg-transparent py-2 pl-9 pr-3 text-sm outline-none placeholder:text-imp-muted-foreground focus:border-imp-primary/50\"\n />\n </div>\n\n {/* Teams list */}\n <div className=\"border rounded-lg border-imp-border bg-imp-card\">\n {teamsQuery.isLoading ? (\n <div className=\"px-4 py-8 text-sm text-center text-imp-muted-foreground\">Loading…</div>\n ) : teamsQuery.error ? (\n <div className=\"px-4 py-8 text-sm text-center text-red-500\">\n {teamsQuery.error instanceof Error ? teamsQuery.error.message : 'Failed to load teams'}\n </div>\n ) : filteredTeams.length === 0 ? (\n <div className=\"px-4 py-8 text-sm text-center text-imp-muted-foreground\">\n {teamSearch\n ? 'No teams match this search.'\n : 'No teams yet. Create one to get started.'}\n </div>\n ) : (\n <div className=\"divide-y divide-imp-border\">\n {filteredTeams.map((team) => {\n const isExpanded = expandedTeamId === team.id;\n return (\n <div key={team.id}>\n <div className=\"flex items-center gap-3 px-3 py-2\">\n <button\n type=\"button\"\n className=\"flex items-center flex-1 gap-3 text-left transition-opacity hover:opacity-80\"\n onClick={() => setExpandedTeamId(isExpanded ? null : team.id)}\n >\n {isExpanded ? (\n <ChevronDown className=\"h-3.5 w-3.5 shrink-0 text-imp-muted-foreground\" />\n ) : (\n <ChevronRight className=\"h-3.5 w-3.5 shrink-0 text-imp-muted-foreground\" />\n )}\n <Users className=\"h-3.5 w-3.5 shrink-0 text-imp-primary\" />\n <div className=\"flex-1 min-w-0\">\n <span className=\"block text-sm font-medium truncate\">{team.name}</span>\n {team.description && (\n <span className=\"block text-xs truncate text-imp-muted-foreground\">\n {team.description}\n </span>\n )}\n </div>\n </button>\n {isAdmin && (\n <button\n type=\"button\"\n onClick={() => handleDelete(team.id)}\n className=\"p-1 rounded shrink-0 text-imp-muted-foreground hover:text-red-500\"\n title=\"Delete team\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </div>\n {isExpanded && (\n <TeamMembersPanel\n teamId={team.id}\n users={users}\n userMap={userMap}\n isAdmin={!!isAdmin}\n />\n )}\n </div>\n );\n })}\n </div>\n )}\n </div>\n </PageLayout>\n );\n}\n\n// ─────────────────────────────────────────────────────────────\n// Team members panel (inline, shown when a team is expanded)\n// ─────────────────────────────────────────────────────────────\n\nfunction TeamMembersPanel({\n teamId,\n users,\n userMap,\n isAdmin,\n}: {\n teamId: string;\n users: AuthUser[];\n userMap: Map<string, AuthUser>;\n isAdmin: boolean;\n}) {\n const { data, isLoading } = useTeam(teamId);\n const addMember = useAddTeamMember(teamId);\n const removeMember = useRemoveTeamMember(teamId);\n\n const members = data?.members ?? [];\n const existingUserIds = new Set(members.map((m) => m.userId));\n\n const getUserLabel = (userId: string) => {\n const u = userMap.get(userId);\n return u?.name || u?.email || userId;\n };\n\n const [selectedUserId, setSelectedUserId] = useState<string | null>(null);\n\n const handleAdd = async () => {\n if (!selectedUserId) {\n return;\n }\n await addMember.mutateAsync({ userId: selectedUserId });\n setSelectedUserId(null);\n };\n\n const handleRemove = async (userId: string) => {\n await removeMember.mutateAsync(userId);\n };\n\n return (\n <div className=\"px-3 pt-2 pb-3 border-t border-imp-border bg-imp-muted/20\">\n {isLoading ? (\n <p className=\"py-3 text-xs text-center text-imp-muted-foreground\">Loading…</p>\n ) : members.length === 0 ? (\n <p className=\"py-2 text-xs text-imp-muted-foreground\">No members yet.</p>\n ) : (\n <div className=\"mb-2 space-y-1\">\n {members.map((member) => (\n <div key={member.id} className=\"flex items-center gap-2 px-2 py-1 text-xs rounded\">\n <div className=\"flex items-center justify-center w-5 h-5 rounded-full shrink-0 bg-imp-primary/10\">\n <User className=\"w-3 h-3 text-imp-primary\" />\n </div>\n <span className=\"flex-1 min-w-0 truncate\">{getUserLabel(member.userId)}</span>\n {isAdmin && (\n <button\n type=\"button\"\n onClick={() => handleRemove(member.userId)}\n className=\"shrink-0 rounded p-0.5 text-imp-muted-foreground hover:text-red-500\"\n title=\"Remove member\"\n >\n <Trash2 className=\"w-3 h-3\" />\n </button>\n )}\n </div>\n ))}\n </div>\n )}\n\n {isAdmin && (\n <div className=\"flex items-center gap-1.5\">\n <MemberSearchCombobox\n users={users}\n excludeIds={existingUserIds}\n selectedUserId={selectedUserId}\n onSelect={setSelectedUserId}\n />\n <button\n type=\"button\"\n onClick={handleAdd}\n disabled={addMember.isPending || !selectedUserId}\n className=\"shrink-0 rounded bg-imp-primary px-2.5 py-1 text-xs font-medium text-imp-primary-foreground hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n {addMember.isPending ? '…' : 'Add'}\n </button>\n </div>\n )}\n </div>\n );\n}\n\n// ─────────────────────────────────────────────────────────────\n// Member search combobox\n// ─────────────────────────────────────────────────────────────\n\nfunction MemberSearchCombobox({\n users,\n excludeIds,\n selectedUserId,\n onSelect,\n}: {\n users: AuthUser[];\n excludeIds: Set<string>;\n selectedUserId: string | null;\n onSelect: (userId: string | null) => void;\n}) {\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState('');\n const containerRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n const selectedUser = selectedUserId ? users.find((u) => u.id === selectedUserId) : null;\n\n const filtered = useMemo(() => {\n const q = query.toLowerCase();\n return users.filter((u) => {\n if (excludeIds.has(u.id)) {\n return false;\n }\n if (!q) {\n return true;\n }\n return (\n u.name?.toLowerCase().includes(q) ||\n u.email?.toLowerCase().includes(q) ||\n u.id.toLowerCase().includes(q)\n );\n });\n }, [users, excludeIds, query]);\n\n useEffect(() => {\n const handleClick = (e: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n if (open) {\n document.addEventListener('mousedown', handleClick);\n return () => document.removeEventListener('mousedown', handleClick);\n }\n }, [open]);\n\n return (\n <div ref={containerRef} className=\"relative flex-1 min-w-0\">\n {selectedUser ? (\n <button\n type=\"button\"\n onClick={() => {\n onSelect(null);\n setQuery('');\n }}\n className=\"flex w-full items-center gap-1.5 rounded border border-imp-border bg-imp-background px-2 py-1 text-xs text-left\"\n >\n <User className=\"w-3 h-3 shrink-0 text-imp-muted-foreground\" />\n <span className=\"flex-1 min-w-0 truncate\">\n {selectedUser.name || selectedUser.email || selectedUser.id}\n </span>\n <X className=\"w-3 h-3 shrink-0 text-imp-muted-foreground\" />\n </button>\n ) : (\n <div className=\"relative\">\n <Search className=\"absolute w-3 h-3 -translate-y-1/2 pointer-events-none left-2 top-1/2 text-imp-muted-foreground\" />\n <input\n ref={inputRef}\n type=\"text\"\n value={query}\n onChange={(e) => {\n setQuery(e.target.value);\n if (!open) {\n setOpen(true);\n }\n }}\n onFocus={() => setOpen(true)}\n placeholder=\"Search users…\"\n className=\"w-full py-1 pl-6 pr-2 text-xs border rounded border-imp-border bg-imp-background placeholder:text-imp-muted-foreground\"\n />\n </div>\n )}\n\n {open && !selectedUser && (\n <div className=\"absolute left-0 z-50 w-full mt-1 border rounded-md shadow-lg top-full border-imp-border bg-imp-background\">\n <div className=\"py-1 overflow-y-auto max-h-40\">\n {filtered.length === 0 ? (\n <p className=\"px-3 py-2 text-xs text-imp-muted-foreground\">No users found.</p>\n ) : (\n filtered.map((u) => (\n <button\n key={u.id}\n type=\"button\"\n onClick={() => {\n onSelect(u.id);\n setQuery('');\n setOpen(false);\n }}\n className=\"flex w-full items-center gap-2 px-2 py-1.5 text-left text-xs hover:bg-imp-muted/50 transition-colors\"\n >\n <User className=\"h-3.5 w-3.5 shrink-0 text-imp-muted-foreground\" />\n <span className=\"flex-1 min-w-0 truncate\">{u.name || u.email || u.id}</span>\n </button>\n ))\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n","/**\n * UserMenuSection — Sidebar footer component showing current user info.\n *\n * Displays the authenticated user's name and role in the sidebar footer area.\n * This is a standalone component — not directly injected via plugin system\n * but available for host apps to use in custom sidebar layouts.\n */\n\nimport { useRbac } from '../providers/RbacProvider';\n\nexport function UserMenuSection({ collapsed = false }: { collapsed?: boolean }) {\n const { user, isAuthenticated, isLoading } = useRbac();\n\n if (isLoading || !isAuthenticated || !user) {\n return null;\n }\n\n const initials = (user.name ?? user.id)[0]?.toUpperCase() ?? '?';\n\n if (collapsed) {\n return (\n <div\n className=\"flex justify-center px-2 py-2\"\n title={`${user.name ?? user.id} (${user.role ?? 'user'})`}\n >\n <div className=\"flex h-8 w-8 items-center justify-center rounded-full bg-imp-primary/10 text-xs font-medium text-imp-primary\">\n {initials}\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"flex items-center gap-3 px-3 py-2\">\n <div className=\"flex h-8 w-8 items-center justify-center rounded-full bg-imp-primary/10 text-xs font-medium text-imp-primary\">\n {initials}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium\">{user.name ?? user.id}</p>\n <p className=\"truncate text-xs text-imp-muted-foreground capitalize\">\n {user.role ?? 'user'}\n </p>\n </div>\n </div>\n );\n}\n\nexport function UserAvatar({ className }: { className?: string }) {\n const { user, isAuthenticated } = useRbac();\n\n if (!isAuthenticated || !user) {\n return null;\n }\n\n const initials = (user.name ?? user.id)[0]?.toUpperCase() ?? '?';\n\n return (\n <div\n className={`flex items-center justify-center rounded-full bg-imp-primary/10 text-xs font-medium text-imp-primary ${className ?? 'h-6 w-6'}`}\n title={user.name ?? user.id}\n >\n {initials}\n </div>\n );\n}\n","/**\n * @invect/rbac/ui — Frontend Plugin Entry Point\n *\n * This is the browser-safe entry point that exports the RBAC frontend plugin.\n * Import via: `import { rbacFrontendPlugin } from '@invect/rbac/ui'`\n *\n * No Node.js dependencies. No @invect/core runtime imports.\n */\n\nimport { Shield } from 'lucide-react';\nimport { RbacProvider, useRbac } from './providers/RbacProvider';\nimport { ShareButton } from './components/ShareButton';\nimport { FlowAccessPanel } from './components/FlowAccessPanel';\nimport { AccessControlPage } from './components/AccessControlPage';\nimport type { InvectFrontendPlugin } from './types';\n\n// ─────────────────────────────────────────────────────────────\n// RBAC Frontend Plugin Definition\n// ─────────────────────────────────────────────────────────────\n\nexport const rbacFrontendPlugin: InvectFrontendPlugin = {\n id: 'rbac',\n name: 'Role-Based Access Control',\n\n // ─── Providers ───\n // Wraps the app tree with RBAC context (current user, permissions cache)\n providers: [RbacProvider],\n\n // ─── Sidebar ───\n sidebar: [\n {\n label: 'Access Control',\n icon: Shield,\n path: '/access',\n position: 'top',\n permission: 'flow:read',\n },\n ],\n\n // ─── Routes ───\n routes: [\n {\n path: '/access',\n component: AccessControlPage,\n },\n ],\n\n // ─── Panel Tabs ───\n panelTabs: [\n {\n context: 'flowEditor',\n label: 'Access',\n icon: Shield,\n component: FlowAccessPanel,\n permission: 'flow:read',\n },\n ],\n\n // ─── Header Actions ───\n headerActions: [\n {\n context: 'flowHeader',\n component: ShareButton,\n permission: 'flow:read',\n },\n ],\n\n // ─── Component Implementations ───\n // These resolve backend-declared componentIds to actual React components\n components: {\n 'rbac.AccessControlPage': AccessControlPage as unknown as React.ComponentType<\n Record<string, unknown>\n >,\n 'rbac.FlowAccessPanel': FlowAccessPanel as unknown as React.ComponentType<\n Record<string, unknown>\n >,\n 'rbac.ShareButton': ShareButton as unknown as React.ComponentType<Record<string, unknown>>,\n },\n\n // ─── Permission Checking ───\n // Delegates to the RbacProvider's cached permissions.\n // This is called by the host app's plugin registry to gate UI elements.\n checkPermission: (_permission: string, _context?) => {\n // We can't call useRbac() here (not in a React component).\n // Return undefined to defer to the registry's default behavior.\n // The actual permission check happens via useRbac().checkPermission()\n // inside each component that needs it.\n return undefined;\n },\n};\n\n// ─────────────────────────────────────────────────────────────\n// Re-exports for direct use\n// ─────────────────────────────────────────────────────────────\n\n// Provider & hook\nexport { RbacProvider, useRbac };\n\n// Components (for custom layouts)\nexport { ShareButton } from './components/ShareButton';\nexport { ShareFlowModal } from './components/ShareFlowModal';\nexport { FlowAccessPanel } from './components/FlowAccessPanel';\nexport { AccessControlPage } from './components/AccessControlPage';\nexport { TeamsPage } from './components/TeamsPage';\nexport { UserMenuSection, UserAvatar } from './components/UserMenuSection';\n\n// Hooks\nexport {\n useAccessibleFlows,\n useFlowAccess,\n useGrantFlowAccess,\n useRevokeFlowAccess,\n} from './hooks/useFlowAccess';\n\nexport {\n useTeams,\n useTeam,\n useMyTeams,\n useUpdateTeam,\n useCreateTeam,\n useDeleteTeam,\n useAddTeamMember,\n useRemoveTeamMember,\n} from './hooks/useTeams';\n\nexport {\n useScopeTree,\n useScopeAccess,\n useGrantScopeAccess,\n useRevokeScopeAccess,\n useEffectiveFlowAccess,\n useMoveFlow,\n usePreviewMove,\n} from './hooks/useScopes';\n\n// Types\nexport type {\n InvectFrontendPlugin,\n PluginSidebarContribution,\n PluginRouteContribution,\n PluginPanelTabContribution,\n PluginHeaderActionContribution,\n PanelTabProps,\n HeaderActionProps,\n PermissionContext,\n} from './types';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["X","ChevronDown","Share2","Share2","Shield","Users","User","useUsers","DropdownMenu","DropdownMenuTrigger","ChevronDown","DropdownMenuContent","DropdownMenuLabel","DropdownMenuSeparator","DropdownMenuItem","Fragment","User","Users","Trash2","Dialog","DialogContent","DialogHeader","DialogTitle","DialogFooter","Dialog","DialogContent","DialogHeader","DialogTitle","User","X","Users","Trash2","ChevronRight","Plus","Dialog","DialogContent","DialogHeader","DialogTitle","DialogFooter","User","Users","X","Workflow","ChevronRight","ExternalLink","Plus","Move","X","User","Users","findScopeNode","Workflow","GripVertical","ChevronDown","ChevronRight","Users","useUsers","PageLayout","Shield","Search","Plus","FolderInput","PageLayout","Users","Plus","Search","ChevronDown","ChevronRight","Trash2","User","X","Shield"],"sources":["../../src/frontend/providers/RbacProvider.tsx","../../src/frontend/hooks/useFlowAccess.ts","../../src/frontend/components/ShareFlowModal.tsx","../../src/frontend/components/ShareButton.tsx","../../src/frontend/components/FlowAccessPanel.tsx","../../src/frontend/hooks/useTeams.ts","../../src/frontend/hooks/useScopes.ts","../../src/frontend/components/access-control/types.ts","../../src/frontend/components/access-control/useUsers.ts","../../src/frontend/components/access-control/AccessTable.tsx","../../src/frontend/components/access-control/FormDialog.tsx","../../src/frontend/components/access-control/MemberCombobox.tsx","../../src/frontend/components/access-control/ScopeDetailPanel.tsx","../../src/frontend/components/access-control/PrincipalCombobox.tsx","../../src/frontend/components/access-control/FlowDetailPanel.tsx","../../src/frontend/components/access-control/MoveConfirmationDialog.tsx","../../src/frontend/stores/accessControlStore.ts","../../src/frontend/components/access-control/AccessControlPage.tsx","../../src/frontend/components/TeamsPage.tsx","../../src/frontend/components/UserMenuSection.tsx","../../src/frontend/index.ts"],"sourcesContent":["/**\n * RBAC Context Provider\n *\n * Wraps the Invect app tree with RBAC state — current user identity,\n * permissions cache, and permission-checking utilities.\n *\n * Fetches GET /plugins/auth/me on mount and caches the result.\n */\n\nimport { createContext, useContext, useCallback, useMemo, type ReactNode } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { useApiClient } from '@invect/ui';\nimport type { AuthMeResponse } from '../../shared/types';\n\n// ─────────────────────────────────────────────────────────────\n// Context Types\n// ─────────────────────────────────────────────────────────────\n\nexport interface RbacContextValue {\n /** Current user identity, null if not authenticated */\n user: AuthMeResponse['identity'];\n /** Whether the user is authenticated */\n isAuthenticated: boolean;\n /** Set of all permissions the user has */\n permissions: Set<string>;\n /** Check if the user has a specific permission */\n checkPermission: (permission: string) => boolean;\n /** Whether the auth/me query is still loading */\n isLoading: boolean;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Context\n// ─────────────────────────────────────────────────────────────\n\nconst RbacContext = createContext<RbacContextValue | null>(null);\n\n// ─────────────────────────────────────────────────────────────\n// Provider\n// ─────────────────────────────────────────────────────────────\n\nexport function RbacProvider({ children }: { children: ReactNode }) {\n const api = useApiClient();\n\n const { data: me, isLoading } = useQuery<AuthMeResponse>({\n queryKey: ['rbac', 'auth', 'me'],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/auth/me`, {\n credentials: 'include',\n });\n if (!response.ok) {\n // If auth endpoint doesn't exist or fails, return unauthenticated\n return {\n identity: null,\n permissions: [],\n isAuthenticated: false,\n };\n }\n return response.json();\n },\n staleTime: 5 * 60 * 1000, // 5 minutes\n retry: 1,\n });\n\n const permissions = useMemo(() => new Set(me?.permissions ?? []), [me?.permissions]);\n\n const checkPermission = useCallback(\n (permission: string): boolean => {\n if (!me?.isAuthenticated) {\n return true; // No auth = allow all (matches core default)\n }\n return permissions.has(permission) || permissions.has('admin:*');\n },\n [me?.isAuthenticated, permissions],\n );\n\n const value = useMemo<RbacContextValue>(\n () => ({\n user: me?.identity ?? null,\n isAuthenticated: me?.isAuthenticated ?? false,\n permissions,\n checkPermission,\n isLoading,\n }),\n [me, permissions, checkPermission, isLoading],\n );\n\n return <RbacContext.Provider value={value}>{children}</RbacContext.Provider>;\n}\n\n// ─────────────────────────────────────────────────────────────\n// Hook\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Access RBAC context — current user, permissions, and permission checking.\n *\n * Must be used within an `<RbacProvider>`.\n * Returns a safe fallback (unauthenticated, allow all) if provider is missing.\n */\nexport function useRbac(): RbacContextValue {\n const ctx = useContext(RbacContext);\n\n if (!ctx) {\n // Graceful fallback — allow everything if RBAC provider isn't mounted\n return {\n user: null,\n isAuthenticated: false,\n permissions: new Set(),\n checkPermission: () => true,\n isLoading: false,\n };\n }\n\n return ctx;\n}\n","/**\n * useFlowAccess — React Query hooks for flow access records\n */\n\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { useApiClient } from '@invect/ui';\nimport type {\n AccessibleFlowsResponse,\n FlowAccessRecord,\n GrantFlowAccessRequest,\n} from '../../shared/types';\n\n/** Fetch access records for a specific flow */\nexport function useFlowAccess(flowId: string | undefined) {\n const api = useApiClient();\n\n return useQuery<{ access: FlowAccessRecord[] }>({\n queryKey: ['rbac', 'flow-access', flowId],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/flows/${flowId}/access`, {\n credentials: 'include',\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch flow access: ${response.status}`);\n }\n return response.json();\n },\n enabled: !!flowId,\n });\n}\n\n/** Fetch all flow IDs accessible to the current user with their effective permission */\nexport function useAccessibleFlows() {\n const api = useApiClient();\n\n return useQuery<AccessibleFlowsResponse>({\n queryKey: ['rbac', 'accessible-flows'],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/flows/accessible`, {\n credentials: 'include',\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(\n err.error || err.message || `Failed to fetch accessible flows: ${response.status}`,\n );\n }\n return response.json();\n },\n });\n}\n\n/** Grant access to a flow */\nexport function useGrantFlowAccess(flowId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (input: GrantFlowAccessRequest) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/flows/${flowId}/access`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n },\n credentials: 'include',\n body: JSON.stringify(input),\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to grant access: ${response.status}`);\n }\n return response.json();\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'flow-access', flowId] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'effective-flow-access', flowId] });\n },\n });\n}\n\n/** Revoke a specific access record */\nexport function useRevokeFlowAccess(flowId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (accessId: string) => {\n const response = await fetch(\n `${api.getBaseURL()}/plugins/rbac/flows/${flowId}/access/${accessId}`,\n {\n method: 'DELETE',\n credentials: 'include',\n },\n );\n if (!response.ok && response.status !== 204) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to revoke access: ${response.status}`);\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'flow-access', flowId] });\n },\n });\n}\n","/**\n * ShareFlowModal — Modal for managing flow access permissions.\n *\n * Shows current access records and allows granting/revoking access.\n */\n\nimport { useState } from 'react';\nimport { ChevronDown, Share2, X } from 'lucide-react';\nimport { useFlowAccess, useGrantFlowAccess, useRevokeFlowAccess } from '../hooks/useFlowAccess';\nimport { useRbac } from '../providers/RbacProvider';\nimport type { FlowAccessPermission } from '../../shared/types';\n\nconst AVATAR_COLORS = [\n 'bg-blue-500/15 text-blue-600 dark:text-blue-400',\n 'bg-violet-500/15 text-violet-600 dark:text-violet-400',\n 'bg-emerald-500/15 text-emerald-600 dark:text-emerald-400',\n 'bg-amber-500/15 text-amber-600 dark:text-amber-400',\n 'bg-rose-500/15 text-rose-600 dark:text-rose-400',\n 'bg-cyan-500/15 text-cyan-600 dark:text-cyan-400',\n 'bg-fuchsia-500/15 text-fuchsia-600 dark:text-fuchsia-400',\n 'bg-orange-500/15 text-orange-600 dark:text-orange-400',\n];\n\nfunction getAvatarColor(id: string): string {\n let hash = 0;\n for (let i = 0; i < id.length; i++) {\n hash = ((hash << 5) - hash + id.charCodeAt(i)) | 0;\n }\n return AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length];\n}\n\nfunction getPermissionColor(permission: FlowAccessPermission): string {\n switch (permission) {\n case 'owner':\n return 'border-amber-500/30 bg-amber-500/5 text-amber-600 dark:text-amber-400';\n case 'editor':\n return 'border-blue-500/30 bg-blue-500/5 text-blue-600 dark:text-blue-400';\n case 'operator':\n return 'border-emerald-500/30 bg-emerald-500/5 text-emerald-600 dark:text-emerald-400';\n case 'viewer':\n default:\n return 'border-imp-border bg-imp-muted/50 text-imp-muted-foreground';\n }\n}\n\nconst PERMISSION_OPTIONS: Array<{ value: FlowAccessPermission; label: string }> = [\n { value: 'viewer', label: 'Viewer' },\n { value: 'operator', label: 'Operator' },\n { value: 'editor', label: 'Editor' },\n { value: 'owner', label: 'Owner' },\n];\n\n// ─────────────────────────────────────────────────────────────\n// Component\n// ─────────────────────────────────────────────────────────────\n\ninterface ShareFlowModalProps {\n flowId: string;\n onClose: () => void;\n}\n\nexport function ShareFlowModal({ flowId, onClose }: ShareFlowModalProps) {\n const { user } = useRbac();\n const { data, isLoading } = useFlowAccess(flowId);\n const grantAccess = useGrantFlowAccess(flowId);\n const revokeAccess = useRevokeFlowAccess(flowId);\n\n const [newPrincipal, setNewPrincipal] = useState('');\n const [newPermission, setNewPermission] = useState<FlowAccessPermission>('viewer');\n const [principalType, setPrincipalType] = useState<'user' | 'team'>('user');\n const [error, setError] = useState<string | null>(null);\n const [openRoleDropdown, setOpenRoleDropdown] = useState<string | null>(null);\n\n const accessRecords = data?.access ?? [];\n\n const handleGrant = async () => {\n if (!newPrincipal.trim()) {\n setError('Please enter a user ID or team ID');\n return;\n }\n\n setError(null);\n try {\n await grantAccess.mutateAsync({\n ...(principalType === 'user' ? { userId: newPrincipal } : { teamId: newPrincipal }),\n permission: newPermission,\n });\n setNewPrincipal('');\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to grant access');\n }\n };\n\n const handleRevoke = async (accessId: string) => {\n try {\n await revokeAccess.mutateAsync(accessId);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to revoke access');\n }\n };\n\n const handleChangeRole = async (\n accessId: string,\n record: (typeof accessRecords)[0],\n newRole: FlowAccessPermission,\n ) => {\n try {\n await grantAccess.mutateAsync({\n ...(record.userId\n ? { userId: record.userId }\n : record.teamId\n ? { teamId: record.teamId }\n : {}),\n permission: newRole,\n });\n setOpenRoleDropdown(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to update role');\n }\n };\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\"\n onClick={onClose}\n >\n <div\n className=\"w-full max-w-md rounded-xl border border-imp-border bg-imp-background p-5 shadow-2xl\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-base font-semibold text-imp-foreground\">Share Flow</h2>\n <button\n onClick={onClose}\n className=\"rounded-lg p-1.5 text-imp-muted-foreground transition-colors hover:bg-imp-muted hover:text-imp-foreground\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n\n {/* Error */}\n {error && (\n <div className=\"mb-3 rounded-lg bg-red-50 px-3 py-2 text-sm text-red-600 dark:bg-red-950/20 dark:text-red-400\">\n {error}\n </div>\n )}\n\n {/* Current access records */}\n <div className=\"mb-4\">\n <h3 className=\"mb-2 text-xs font-medium uppercase tracking-wide text-imp-muted-foreground\">\n People with access\n </h3>\n {isLoading ? (\n <div className=\"py-4 text-center text-sm text-imp-muted-foreground\">Loading...</div>\n ) : accessRecords.length === 0 ? (\n <div className=\"py-4 text-center text-sm text-imp-muted-foreground\">\n No flow-specific access records yet.\n </div>\n ) : (\n <div className=\"max-h-48 space-y-0.5 overflow-y-auto\">\n {accessRecords.map((record) => {\n const principalId = record.userId ?? record.teamId ?? '?';\n const isCurrentUser = record.userId === user?.id;\n const isRoleDropdownOpen = openRoleDropdown === record.id;\n\n return (\n <div\n key={record.id}\n className=\"flex items-center justify-between rounded-lg px-2.5 py-2 transition-colors hover:bg-imp-muted/30\"\n >\n <div className=\"flex items-center gap-2.5 min-w-0\">\n <div\n className={`flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-xs font-semibold ${getAvatarColor(principalId)}`}\n >\n {principalId[0]?.toUpperCase()}\n </div>\n <span className=\"truncate text-sm font-medium text-imp-foreground\">\n {principalId}\n {isCurrentUser && (\n <span className=\"ml-1 font-normal text-imp-muted-foreground\">(you)</span>\n )}\n </span>\n </div>\n <div className=\"relative\">\n {isCurrentUser ? (\n <span\n className={`inline-flex rounded-full border px-2.5 py-0.5 text-xs font-medium capitalize ${getPermissionColor(record.permission)}`}\n >\n {record.permission}\n </span>\n ) : (\n <>\n <button\n type=\"button\"\n onClick={() =>\n setOpenRoleDropdown(isRoleDropdownOpen ? null : record.id)\n }\n className={`inline-flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-xs font-medium capitalize transition-colors hover:bg-imp-muted/50 ${getPermissionColor(record.permission)}`}\n >\n {record.permission}\n <ChevronDown className=\"h-3 w-3\" />\n </button>\n {isRoleDropdownOpen && (\n <>\n <div\n className=\"fixed inset-0 z-10\"\n onClick={() => setOpenRoleDropdown(null)}\n />\n <div className=\"absolute right-0 top-full z-20 mt-1 w-36 rounded-lg border border-imp-border bg-imp-background py-1 shadow-lg\">\n {PERMISSION_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n className={`w-full px-3 py-1.5 text-left text-xs ${\n record.permission === opt.value\n ? 'bg-imp-muted font-medium text-imp-foreground'\n : 'text-imp-foreground hover:bg-imp-muted/50'\n }`}\n onClick={() => handleChangeRole(record.id, record, opt.value)}\n >\n {opt.label}\n </button>\n ))}\n <div className=\"my-1 border-t border-imp-border\" />\n <button\n type=\"button\"\n className=\"w-full px-3 py-1.5 text-left text-xs text-imp-destructive hover:bg-imp-destructive/10\"\n onClick={() => {\n handleRevoke(record.id);\n setOpenRoleDropdown(null);\n }}\n >\n Remove access\n </button>\n </div>\n </>\n )}\n </>\n )}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n\n {/* Grant new access */}\n <div className=\"border-t border-imp-border pt-4\">\n <h3 className=\"mb-2.5 text-xs font-medium uppercase tracking-wide text-imp-muted-foreground\">\n Add people\n </h3>\n <div className=\"flex gap-2\">\n {/* Principal type toggle */}\n <button\n type=\"button\"\n onClick={() => setPrincipalType(principalType === 'user' ? 'team' : 'user')}\n className=\"shrink-0 rounded-lg border border-imp-border bg-imp-background px-2.5 py-1.5 text-xs font-medium text-imp-foreground transition-colors hover:bg-imp-muted/50\"\n >\n {principalType === 'user' ? 'User' : 'Team'}\n </button>\n\n {/* Principal ID input */}\n <input\n type=\"text\"\n value={newPrincipal}\n onChange={(e) => setNewPrincipal(e.target.value)}\n placeholder={principalType === 'user' ? 'User ID' : 'Team ID'}\n className=\"flex-1 rounded-lg border border-imp-border bg-imp-background px-3 py-1.5 text-sm placeholder:text-imp-muted-foreground focus:border-imp-primary/50 focus:outline-none\"\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n handleGrant();\n }\n }}\n />\n\n {/* Permission selector */}\n <button\n type=\"button\"\n onClick={() => {\n const idx = PERMISSION_OPTIONS.findIndex((o) => o.value === newPermission);\n const next = PERMISSION_OPTIONS[(idx + 1) % PERMISSION_OPTIONS.length];\n setNewPermission(next.value);\n }}\n className={`shrink-0 rounded-lg border px-2.5 py-1.5 text-xs font-medium capitalize transition-colors ${getPermissionColor(newPermission)}`}\n >\n {newPermission}\n </button>\n\n {/* Submit */}\n <button\n onClick={handleGrant}\n disabled={grantAccess.isPending}\n className=\"shrink-0 rounded-lg bg-imp-primary px-3.5 py-1.5 text-sm font-medium text-imp-primary-foreground transition-colors hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n <Share2 className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","/**\n * ShareButton — Header action component for the flow editor.\n *\n * Renders a \"Share\" button in the flow header that opens the ShareFlowModal.\n * Registered as a headerAction contribution for the 'flowHeader' context.\n */\n\nimport { useState } from 'react';\nimport { Share2 } from 'lucide-react';\nimport { useAccessibleFlows } from '../hooks/useFlowAccess';\nimport { useRbac } from '../providers/RbacProvider';\nimport { ShareFlowModal } from './ShareFlowModal';\nimport type { HeaderActionProps } from '../types';\n\nexport function ShareButton({ flowId }: HeaderActionProps) {\n const [isOpen, setIsOpen] = useState(false);\n const { isAuthenticated, checkPermission } = useRbac();\n const { data } = useAccessibleFlows();\n\n if (!flowId) {\n return null;\n }\n\n const isAdmin = isAuthenticated && checkPermission('admin:*');\n const myPermission = isAdmin ? 'owner' : (data?.permissions?.[flowId] ?? null);\n\n if (myPermission !== 'owner') {\n return null;\n }\n\n return (\n <>\n <button\n onClick={() => setIsOpen(true)}\n className=\"inline-flex items-center gap-2 rounded-md border border-imp-border px-3 py-1.5 text-sm font-medium text-imp-foreground transition-colors hover:border-imp-primary/50 hover:bg-imp-muted\"\n >\n <Share2 className=\"h-4 w-4\" />\n Share\n </button>\n {isOpen && <ShareFlowModal flowId={flowId} onClose={() => setIsOpen(false)} />}\n </>\n );\n}\n","/**\n * FlowAccessPanel — Panel tab for the flow editor.\n *\n * Shows the current access records for the selected flow in a\n * compact list. Registered as a panelTab contribution for the\n * 'flowEditor' context.\n */\n\nimport { Shield, Users, User } from 'lucide-react';\nimport { useFlowAccess } from '../hooks/useFlowAccess';\nimport { useRbac } from '../providers/RbacProvider';\nimport type { PanelTabProps } from '../types';\n\nexport function FlowAccessPanel({ flowId }: PanelTabProps) {\n const { user } = useRbac();\n const { data, isLoading, error } = useFlowAccess(flowId);\n\n const accessRecords = data?.access ?? [];\n const myRecord = accessRecords.find((r) => r.userId === user?.id);\n\n return (\n <div className=\"flex h-full flex-col p-4\">\n {/* Header */}\n <div className=\"mb-4 flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <Shield className=\"h-4 w-4 text-imp-muted-foreground\" />\n <h3 className=\"text-sm font-medium\">Access Control</h3>\n </div>\n {myRecord && (\n <span className=\"rounded-full border border-imp-border px-2 py-0.5 text-xs font-medium capitalize\">\n {myRecord.permission}\n </span>\n )}\n </div>\n\n {/* Content */}\n {isLoading ? (\n <div className=\"flex flex-1 items-center justify-center\">\n <span className=\"text-sm text-imp-muted-foreground\">Loading access records...</span>\n </div>\n ) : error ? (\n <div className=\"flex flex-1 items-center justify-center\">\n <span className=\"text-sm text-red-500\">\n {error instanceof Error ? error.message : 'Failed to load access records'}\n </span>\n </div>\n ) : accessRecords.length === 0 ? (\n <div className=\"flex flex-1 flex-col items-center justify-center gap-2\">\n <Users className=\"h-8 w-8 text-imp-muted-foreground/50\" />\n <p className=\"text-sm text-imp-muted-foreground\">No access records</p>\n <p className=\"text-xs text-imp-muted-foreground\">Use the Share button to grant access.</p>\n </div>\n ) : (\n <div className=\"flex-1 space-y-1 overflow-y-auto\">\n {accessRecords.map((record) => (\n <div\n key={record.id}\n className=\"flex items-center gap-3 rounded-md px-3 py-2 bg-imp-muted/30\"\n >\n <div className=\"flex h-7 w-7 items-center justify-center rounded-full bg-imp-primary/10\">\n {record.teamId ? (\n <Users className=\"h-3.5 w-3.5 text-imp-primary\" />\n ) : (\n <User className=\"h-3.5 w-3.5 text-imp-primary\" />\n )}\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"truncate text-sm\">\n {record.userId ?? record.teamId}\n {record.userId === user?.id && (\n <span className=\"ml-1 text-imp-muted-foreground\">(you)</span>\n )}\n </p>\n {record.expiresAt && (\n <p className=\"text-xs text-imp-muted-foreground\">\n Expires {new Date(record.expiresAt).toLocaleDateString()}\n </p>\n )}\n </div>\n <span className=\"rounded-full bg-imp-muted px-2 py-0.5 text-xs font-medium capitalize\">\n {record.permission}\n </span>\n </div>\n ))}\n </div>\n )}\n\n {/* Footer — summary */}\n {accessRecords.length > 0 && (\n <div className=\"mt-3 border-t border-imp-border pt-3\">\n <p className=\"text-xs text-imp-muted-foreground\">\n {accessRecords.length} {accessRecords.length === 1 ? 'person' : 'people'} with access\n </p>\n </div>\n )}\n </div>\n );\n}\n","/**\n * useTeams — React Query hooks for team management\n */\n\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport { useApiClient } from '@invect/ui';\nimport type {\n Team,\n TeamWithMembers,\n CreateTeamRequest,\n UpdateTeamRequest,\n AddTeamMemberRequest,\n TeamMember,\n} from '../../shared/types';\n\n/** List all teams */\nexport function useTeams() {\n const api = useApiClient();\n\n return useQuery<{ teams: Team[] }>({\n queryKey: ['rbac', 'teams'],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/teams`, {\n credentials: 'include',\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch teams: ${response.status}`);\n }\n return response.json();\n },\n });\n}\n\n/** Get a single team with members */\nexport function useTeam(teamId: string | undefined) {\n const api = useApiClient();\n\n return useQuery<TeamWithMembers>({\n queryKey: ['rbac', 'team', teamId],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/teams/${teamId}`, {\n credentials: 'include',\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch team: ${response.status}`);\n }\n return response.json();\n },\n enabled: !!teamId,\n });\n}\n\n/** Get current user's teams */\nexport function useMyTeams() {\n const api = useApiClient();\n\n return useQuery<{ teams: Team[] }>({\n queryKey: ['rbac', 'my-teams'],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/my-teams`, {\n credentials: 'include',\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch my teams: ${response.status}`);\n }\n return response.json();\n },\n });\n}\n\n/** Create a team */\nexport function useCreateTeam() {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (input: CreateTeamRequest) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/teams`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify(input),\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to create team: ${response.status}`);\n }\n return response.json() as Promise<Team>;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'teams'] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n },\n });\n}\n\n/** Update a team */\nexport function useUpdateTeam(teamId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (input: UpdateTeamRequest) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/teams/${teamId}`, {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify(input),\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to update team: ${response.status}`);\n }\n return response.json();\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'teams'] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'team', teamId] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n },\n });\n}\n\n/** Delete a team */\nexport function useDeleteTeam() {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (teamId: string) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/teams/${teamId}`, {\n method: 'DELETE',\n credentials: 'include',\n });\n if (!response.ok && response.status !== 204) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to delete team: ${response.status}`);\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'teams'] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n },\n });\n}\n\n/** Add a member to a team */\nexport function useAddTeamMember(teamId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (input: AddTeamMemberRequest) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/teams/${teamId}/members`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify(input),\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to add member: ${response.status}`);\n }\n return response.json() as Promise<TeamMember>;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'team', teamId] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'teams'] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n },\n });\n}\n\n/** Remove a member from a team */\nexport function useRemoveTeamMember(teamId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (userId: string) => {\n const response = await fetch(\n `${api.getBaseURL()}/plugins/rbac/teams/${teamId}/members/${userId}`,\n {\n method: 'DELETE',\n credentials: 'include',\n },\n );\n if (!response.ok && response.status !== 204) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to remove member: ${response.status}`);\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'team', teamId] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'teams'] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n },\n });\n}\n","import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { useApiClient } from '@invect/ui';\nimport type {\n EffectiveFlowAccessResponse,\n GrantScopeAccessRequest,\n MovePreviewRequest,\n MovePreviewResponse,\n ScopeAccessRecord,\n ScopeTreeResponse,\n} from '../../shared/types';\n\nexport function useScopeTree() {\n const api = useApiClient();\n\n return useQuery<ScopeTreeResponse>({\n queryKey: ['rbac', 'scope-tree'],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/scopes/tree`, {\n credentials: 'include',\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to fetch scope tree: ${response.status}`);\n }\n return response.json();\n },\n });\n}\n\nexport function useScopeAccess(scopeId: string | undefined) {\n const api = useApiClient();\n\n return useQuery<{ access: ScopeAccessRecord[] }>({\n queryKey: ['rbac', 'scope-access', scopeId],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/scopes/${scopeId}/access`, {\n credentials: 'include',\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to fetch scope access: ${response.status}`);\n }\n return response.json();\n },\n enabled: !!scopeId,\n });\n}\n\nexport function useGrantScopeAccess(scopeId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (input: GrantScopeAccessRequest) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/scopes/${scopeId}/access`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify(input),\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to grant scope access: ${response.status}`);\n }\n return response.json() as Promise<ScopeAccessRecord>;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-access', scopeId] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n },\n });\n}\n\nexport function useRevokeScopeAccess(scopeId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (accessId: string) => {\n const response = await fetch(\n `${api.getBaseURL()}/plugins/rbac/scopes/${scopeId}/access/${accessId}`,\n {\n method: 'DELETE',\n credentials: 'include',\n },\n );\n if (!response.ok && response.status !== 204) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to revoke scope access: ${response.status}`);\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-access', scopeId] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n },\n });\n}\n\nexport function useEffectiveFlowAccess(flowId: string | undefined) {\n const api = useApiClient();\n\n return useQuery<EffectiveFlowAccessResponse>({\n queryKey: ['rbac', 'effective-flow-access', flowId],\n queryFn: async () => {\n const response = await fetch(\n `${api.getBaseURL()}/plugins/rbac/flows/${flowId}/effective-access`,\n { credentials: 'include' },\n );\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to fetch effective flow access: ${response.status}`);\n }\n return response.json();\n },\n enabled: !!flowId,\n });\n}\n\nexport function useMoveFlow(flowId: string) {\n const api = useApiClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (scopeId: string | null) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/flows/${flowId}/scope`, {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify({ scopeId }),\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to move flow: ${response.status}`);\n }\n return response.json() as Promise<{\n success: boolean;\n flowId: string;\n scopeId: string | null;\n }>;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['rbac', 'scope-tree'] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'accessible-flows'] });\n queryClient.invalidateQueries({ queryKey: ['rbac', 'effective-flow-access', flowId] });\n },\n });\n}\n\nexport function usePreviewMove() {\n const api = useApiClient();\n\n return useMutation({\n mutationFn: async (input: MovePreviewRequest) => {\n const response = await fetch(`${api.getBaseURL()}/plugins/rbac/preview-move`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify(input),\n });\n if (!response.ok) {\n const err = await response.json().catch(() => ({}));\n throw new Error(err.error || `Failed to preview move: ${response.status}`);\n }\n return response.json() as Promise<MovePreviewResponse>;\n },\n });\n}\n","import type { FlowAccessPermission, MovePreviewRequest } from '../../../shared/types';\n\nexport interface AuthUser {\n id: string;\n name?: string;\n email?: string;\n}\n\nexport type SelectedItem =\n | { kind: 'flow'; id: string; name: string }\n | { kind: 'team'; id: string; name: string };\n\nexport type PendingMove = MovePreviewRequest & { name: string };\n\nexport type PrincipalSelection = { type: 'user' | 'team'; id: string };\n\nexport interface AccessRow {\n id: string;\n label: string;\n kind: 'user' | 'team';\n permission: FlowAccessPermission | null;\n source: string;\n group?: string;\n canRemove: boolean;\n onPermissionChange?: (permission: FlowAccessPermission) => void;\n onRemove?: () => void;\n}\n\nexport function formatPermissionLabel(permission: FlowAccessPermission): string {\n switch (permission) {\n case 'owner':\n return 'Owner';\n case 'editor':\n return 'Editor';\n case 'operator':\n return 'Operator';\n case 'viewer':\n default:\n return 'Viewer';\n }\n}\n\nexport function getPermissionBadgeClasses(_permission: FlowAccessPermission): string {\n return 'border-imp-border text-imp-muted-foreground';\n}\n","import { useQuery } from '@tanstack/react-query';\nimport { useApiClient } from '@invect/ui';\nimport type { AuthUser } from './types';\n\nexport function useUsers(): AuthUser[] {\n const api = useApiClient();\n\n const { data } = useQuery<{ users: AuthUser[] }>({\n queryKey: ['rbac', 'auth-users'],\n queryFn: async () => {\n const response = await fetch(`${api.getBaseURL()}/plugins/auth/users?limit=200`, {\n credentials: 'include',\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch users: ${response.status}`);\n }\n return response.json();\n },\n staleTime: 1000 * 60 * 5, // 5 min — shared across all consumers\n gcTime: 1000 * 60 * 10,\n });\n\n return data?.users ?? [];\n}\n","import { Fragment, useState } from 'react';\nimport { clsx } from 'clsx';\nimport { ChevronDown, Trash2, User, Users } from 'lucide-react';\nimport {\n Dialog,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@invect/ui';\nimport { twMerge } from 'tailwind-merge';\nimport type { AccessRow } from './types';\nimport type { FlowAccessPermission } from '../../../shared/types';\nimport { getPermissionBadgeClasses } from './types';\n\nfunction cn(...inputs: Parameters<typeof clsx>) {\n return twMerge(clsx(inputs));\n}\n\nconst ROLE_OPTIONS: Array<{\n value: FlowAccessPermission;\n label: string;\n description: string;\n}> = [\n { value: 'viewer', label: 'Viewer', description: 'Can inspect the flow.' },\n { value: 'operator', label: 'Operator', description: 'Can inspect and run the flow.' },\n { value: 'editor', label: 'Editor', description: 'Can inspect, run, and edit the flow.' },\n { value: 'owner', label: 'Owner', description: 'Can edit and manage sharing.' },\n];\n\nexport function RoleSelector({\n value,\n onChange,\n}: {\n value: FlowAccessPermission;\n onChange: (permission: FlowAccessPermission) => void;\n}) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n className={cn(\n 'inline-flex w-full items-center justify-between gap-1 rounded-md border px-2.5 py-1.5 text-sm font-medium capitalize',\n getPermissionBadgeClasses(value),\n )}\n >\n <span className=\"truncate\">{value}</span>\n <ChevronDown className=\"h-3.5 w-3.5 shrink-0\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-56\">\n <DropdownMenuLabel className=\"text-xs\">Select role</DropdownMenuLabel>\n <DropdownMenuSeparator />\n {ROLE_OPTIONS.map((role) => (\n <DropdownMenuItem\n key={role.value}\n onSelect={() => onChange(role.value)}\n className={cn(\n 'items-start gap-0 px-2 py-2',\n value === role.value && 'bg-accent text-accent-foreground',\n )}\n >\n <div className=\"min-w-0 text-left\">\n <div className=\"text-sm font-medium\">{role.label}</div>\n <div className=\"text-xs text-muted-foreground\">{role.description}</div>\n </div>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport function OptionalRoleSelector({\n value,\n onChange,\n emptyLabel = 'No direct access',\n}: {\n value: FlowAccessPermission | null;\n onChange: (permission: FlowAccessPermission | null) => void;\n emptyLabel?: string;\n}) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n className={cn(\n 'inline-flex w-40 items-center justify-between gap-1 rounded-md border px-2.5 py-1.5 text-sm font-medium capitalize',\n value\n ? getPermissionBadgeClasses(value)\n : 'border-imp-border text-imp-muted-foreground hover:bg-imp-muted/50',\n )}\n >\n <span className=\"truncate\">{value ?? emptyLabel}</span>\n <ChevronDown className=\"h-3.5 w-3.5 shrink-0\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-56\">\n <DropdownMenuLabel className=\"text-xs\">Set access level</DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onSelect={() => onChange(null)}\n className={cn('px-2 py-2 text-sm', value === null && 'bg-accent text-accent-foreground')}\n >\n {emptyLabel}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n {ROLE_OPTIONS.map((role) => (\n <DropdownMenuItem\n key={role.value}\n onSelect={() => onChange(role.value)}\n className={cn(\n 'items-start gap-0 px-2 py-2',\n value === role.value && 'bg-accent text-accent-foreground',\n )}\n >\n <div className=\"min-w-0 text-left\">\n <div className=\"text-sm font-medium\">{role.label}</div>\n <div className=\"text-xs text-muted-foreground\">{role.description}</div>\n </div>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport function AccessTable({\n rows,\n isLoading,\n emptyLabel,\n}: {\n rows: AccessRow[];\n isLoading: boolean;\n emptyLabel: string;\n}) {\n const [pendingRemovalRow, setPendingRemovalRow] = useState<AccessRow | null>(null);\n\n const removalDialogCopy = pendingRemovalRow\n ? pendingRemovalRow.group === 'Members'\n ? {\n title: 'Remove team member',\n body: `Remove \"${pendingRemovalRow.label}\" from team?`,\n confirmLabel: 'Remove member',\n }\n : {\n title: pendingRemovalRow.kind === 'team' ? 'Revoke team access' : 'Revoke user access',\n body:\n pendingRemovalRow.kind === 'team'\n ? `Remove direct access for ${pendingRemovalRow.label}?`\n : `Remove direct access for ${pendingRemovalRow.label}?`,\n confirmLabel: 'Remove access',\n }\n : null;\n\n if (isLoading) {\n return <div className=\"px-2 py-4 text-sm text-center text-imp-muted-foreground\">Loading…</div>;\n }\n if (rows.length === 0) {\n return (\n <div className=\"px-2 py-4 text-sm text-center text-imp-muted-foreground\">{emptyLabel}</div>\n );\n }\n\n const groups: Array<{ label: string; rows: AccessRow[] }> = [];\n for (const row of rows) {\n const groupLabel = row.group ?? '';\n const existing = groups.find((g) => g.label === groupLabel);\n if (existing) {\n existing.rows.push(row);\n } else {\n groups.push({ label: groupLabel, rows: [row] });\n }\n }\n const hasGroups = groups.length > 1;\n\n return (\n <>\n <table className=\"w-full text-sm table-fixed\">\n <colgroup>\n <col />\n <col className=\"w-36\" />\n <col className=\"w-10\" />\n </colgroup>\n <tbody>\n {groups.map((group) => (\n <Fragment key={group.label || '_default'}>\n {hasGroups && group.label && (\n <tr>\n <td\n colSpan={3}\n className=\"px-3 pt-4 pb-1.5 text-[10px] font-semibold uppercase tracking-wider text-imp-muted-foreground\"\n >\n {group.label}\n </td>\n </tr>\n )}\n {group.rows.map((row, rowIndex) => (\n <tr\n key={row.id}\n className={cn(\n 'hover:bg-imp-muted/20',\n rowIndex > 0 && 'border-t border-imp-border',\n )}\n >\n <td className=\"px-3 py-2.5\">\n <div className=\"flex items-center gap-3\">\n <div\n className={cn(\n 'flex h-7 w-7 shrink-0 items-center justify-center rounded-full',\n row.kind === 'user' ? 'bg-imp-primary/10' : 'bg-imp-muted',\n )}\n >\n {row.kind === 'user' ? (\n <User className=\"h-3.5 w-3.5 text-imp-primary\" />\n ) : (\n <Users className=\"h-3.5 w-3.5 text-imp-muted-foreground\" />\n )}\n </div>\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium truncate\">{row.label}</span>\n {row.kind === 'team' && (\n <span className=\"shrink-0 rounded border border-imp-border px-1.5 py-0.5 text-[11px] font-medium text-imp-muted-foreground\">\n Team\n </span>\n )}\n </div>\n {row.source && row.source !== 'Direct grant' && row.source !== 'Member' && (\n <span className=\"text-[11px] text-imp-muted-foreground\">\n {row.source}\n </span>\n )}\n </div>\n </div>\n </td>\n <td className=\"px-3 py-2.5 text-center\">\n {row.permission ? (\n row.onPermissionChange ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n className={cn(\n 'inline-flex w-32 items-center justify-between gap-1 rounded-full border px-2.5 py-1 text-xs font-medium capitalize hover:bg-imp-muted/50',\n getPermissionBadgeClasses(row.permission),\n )}\n title={row.source}\n >\n <span className=\"truncate\">{row.permission}</span>\n <ChevronDown className=\"h-3.5 w-3.5 shrink-0\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-64\">\n <DropdownMenuLabel className=\"text-xs\">\n Change access role\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n {ROLE_OPTIONS.map((role) => (\n <DropdownMenuItem\n key={role.value}\n onSelect={() => row.onPermissionChange?.(role.value)}\n className={cn(\n 'items-start gap-0 px-2 py-2',\n row.permission === role.value &&\n 'bg-accent text-accent-foreground',\n )}\n >\n <div className=\"min-w-0 text-left\">\n <div className=\"text-sm font-medium\">{role.label}</div>\n <div className=\"text-xs text-muted-foreground\">\n {role.description}\n </div>\n </div>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n ) : (\n <span\n className={cn(\n 'inline-flex w-32 justify-center rounded-full border px-2.5 py-1 text-xs font-medium capitalize',\n getPermissionBadgeClasses(row.permission),\n )}\n title={row.source}\n >\n {row.permission}\n </span>\n )\n ) : null}\n </td>\n <td className=\"px-3 py-2.5 text-center\">\n {row.canRemove && row.onRemove ? (\n <button\n type=\"button\"\n onClick={() => setPendingRemovalRow(row)}\n className=\"p-1 rounded text-imp-muted-foreground hover:bg-imp-destructive/10 hover:text-imp-destructive\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </button>\n ) : null}\n </td>\n </tr>\n ))}\n </Fragment>\n ))}\n </tbody>\n </table>\n\n <Dialog\n open={!!pendingRemovalRow}\n onOpenChange={(open) => !open && setPendingRemovalRow(null)}\n >\n <DialogContent className=\"max-w-sm border-imp-border bg-imp-background text-imp-foreground sm:max-w-sm\">\n <DialogHeader>\n <DialogTitle className=\"text-sm font-semibold\">{removalDialogCopy?.title}</DialogTitle>\n </DialogHeader>\n <p className=\"text-sm text-imp-muted-foreground\">{removalDialogCopy?.body}</p>\n <DialogFooter className=\"justify-between w-full sm:gap-2\">\n <button\n type=\"button\"\n onClick={() => setPendingRemovalRow(null)}\n className=\"rounded-md mr-auto border border-imp-border px-3 py-1.5 text-xs font-medium text-imp-muted-foreground hover:text-imp-foreground\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={() => {\n pendingRemovalRow?.onRemove?.();\n setPendingRemovalRow(null);\n }}\n className=\"rounded-md bg-red-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-red-700\"\n >\n {removalDialogCopy?.confirmLabel}\n </button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@invect/ui';\n\nexport function FormDialog({\n open,\n onClose,\n title,\n children,\n}: {\n open: boolean;\n onClose: () => void;\n title: string;\n children: React.ReactNode;\n}) {\n return (\n <Dialog open={open} onOpenChange={(nextOpen) => !nextOpen && onClose()}>\n <DialogContent className=\"max-w-md p-4 border-imp-border bg-imp-background text-imp-foreground sm:max-w-md\">\n <DialogHeader className=\"mb-1\">\n <DialogTitle className=\"text-sm font-semibold\">{title}</DialogTitle>\n </DialogHeader>\n {children}\n </DialogContent>\n </Dialog>\n );\n}\n","import { useRef, useState } from 'react';\nimport { User, X } from 'lucide-react';\nimport type { AuthUser } from './types';\n\nexport function MemberCombobox({\n users,\n excludeIds,\n selectedUserIds,\n onSelect,\n}: {\n users: AuthUser[];\n excludeIds: Set<string>;\n selectedUserIds: string[];\n onSelect: (userIds: string[]) => void;\n}) {\n const [query, setQuery] = useState('');\n const [open, setOpen] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const selectedSet = new Set(selectedUserIds);\n\n const filteredUsers = users.filter((user) => {\n if (excludeIds.has(user.id)) {\n return false;\n }\n if (selectedSet.has(user.id)) {\n return false;\n }\n const haystack = `${user.name || ''} ${user.email || ''} ${user.id}`.toLowerCase();\n return haystack.includes(query.toLowerCase());\n });\n\n const toggle = (userId: string) => {\n onSelect(\n selectedSet.has(userId)\n ? selectedUserIds.filter((id) => id !== userId)\n : [...selectedUserIds, userId],\n );\n };\n\n return (\n <div\n ref={containerRef}\n className=\"relative\"\n onBlur={(e) => {\n if (!containerRef.current?.contains(e.relatedTarget as Node)) {\n setOpen(false);\n }\n }}\n >\n <div\n className=\"flex min-h-[2.5rem] w-full cursor-text flex-wrap gap-1.5 rounded-md border border-imp-border bg-imp-background px-2 py-1.5 focus-within:border-imp-primary/50\"\n onClick={() => setOpen(true)}\n >\n {selectedUserIds.map((userId) => {\n const user = users.find((u) => u.id === userId);\n const label = user?.name || user?.email || userId;\n return (\n <span\n key={userId}\n className=\"inline-flex items-center gap-1 rounded-md border border-imp-border bg-imp-muted px-2 py-0.5 text-xs font-medium text-imp-foreground\"\n >\n <User className=\"h-3 w-3 shrink-0 text-imp-muted-foreground\" />\n <span className=\"max-w-[140px] truncate\">{label}</span>\n <button\n type=\"button\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={(e) => {\n e.stopPropagation();\n toggle(userId);\n }}\n className=\"ml-0.5 text-imp-muted-foreground hover:text-imp-foreground\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </span>\n );\n })}\n <input\n value={query}\n onChange={(e) => {\n setQuery(e.target.value);\n setOpen(true);\n }}\n onFocus={() => setOpen(true)}\n placeholder={selectedUserIds.length === 0 ? 'Search users…' : 'Add more…'}\n className=\"min-w-[120px] flex-1 bg-transparent text-sm outline-none placeholder:text-imp-muted-foreground\"\n />\n </div>\n {open && (\n <div className=\"absolute left-0 z-20 mt-1 w-full overflow-y-auto rounded-md border border-imp-border bg-imp-background shadow-lg top-full max-h-52\">\n {filteredUsers.length === 0 ? (\n <div className=\"px-3 py-2 text-xs text-imp-muted-foreground\">\n {query ? 'No matches.' : 'No more users to add.'}\n </div>\n ) : (\n filteredUsers.map((user) => (\n <button\n key={user.id}\n type=\"button\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n toggle(user.id);\n setQuery('');\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-imp-muted/50\"\n >\n <User className=\"h-4 w-4 shrink-0 text-imp-muted-foreground\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate font-medium\">{user.name || user.email || user.id}</div>\n {user.name && user.email && (\n <div className=\"truncate text-xs text-imp-muted-foreground\">{user.email}</div>\n )}\n </div>\n </button>\n ))\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useMemo, useState } from 'react';\nimport { ChevronRight, Plus, Trash2, Users } from 'lucide-react';\nimport { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@invect/ui';\nimport {\n useAddTeamMember,\n useDeleteTeam,\n useTeam,\n useRemoveTeamMember,\n} from '../../hooks/useTeams';\nimport { useGrantScopeAccess, useRevokeScopeAccess, useScopeAccess } from '../../hooks/useScopes';\nimport type { FlowAccessPermission, Team } from '../../../shared/types';\nimport type { AccessRow, AuthUser } from './types';\nimport { AccessTable, OptionalRoleSelector, RoleSelector } from './AccessTable';\nimport { FormDialog } from './FormDialog';\nimport { MemberCombobox } from './MemberCombobox';\n\nexport function ScopeDetailPanel({\n scopeId,\n scopeName,\n users,\n userMap,\n teams,\n isAdmin,\n}: {\n scopeId: string;\n scopeName: string;\n users: AuthUser[];\n userMap: Map<string, AuthUser>;\n teams: Team[];\n isAdmin: boolean;\n}) {\n const scopeQuery = useTeam(scopeId);\n const scopeAccessQuery = useScopeAccess(scopeId);\n const grantScopeAccess = useGrantScopeAccess(scopeId);\n const revokeScopeAccess = useRevokeScopeAccess(scopeId);\n const addTeamMember = useAddTeamMember(scopeId);\n const removeTeamMember = useRemoveTeamMember(scopeId);\n const deleteScope = useDeleteTeam();\n\n const [showGrantDialog, setShowGrantDialog] = useState(false);\n const [showMemberDialog, setShowMemberDialog] = useState(false);\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [permission, setPermission] = useState<FlowAccessPermission>('viewer');\n const [grantUserIds, setGrantUserIds] = useState<string[]>([]);\n const [memberUserIds, setMemberUserIds] = useState<string[]>([]);\n\n const members = scopeQuery.data?.members ?? [];\n const scopeAccess = scopeAccessQuery.data?.access ?? [];\n const existingMemberIds = new Set(members.map((member) => member.userId));\n const existingScopeUserIds = new Set(\n scopeAccess.map((record) => record.userId).filter(Boolean) as string[],\n );\n const teamRoleRecord = scopeAccess.find((record) => record.teamId === scopeId) ?? null;\n const childTeams = teams.filter((team) => team.parentId === scopeId);\n\n const isLoading = scopeQuery.isLoading || scopeAccessQuery.isLoading;\n\n const accessRows = useMemo(() => {\n const rows: AccessRow[] = [];\n for (const member of members) {\n const user = userMap.get(member.userId);\n rows.push({\n id: `member:${member.id}`,\n label: user?.name || user?.email || member.userId,\n kind: 'user',\n permission: null,\n source: 'Member',\n group: 'Members',\n canRemove: isAdmin,\n onRemove: () => removeTeamMember.mutate(member.userId),\n });\n }\n for (const record of scopeAccess) {\n if (record.teamId === scopeId) {\n continue;\n }\n const isUser = !!record.userId;\n const userId = record.userId ?? null;\n rows.push({\n id: `access:${record.id}`,\n label: isUser\n ? userMap.get(userId ?? '')?.name ||\n userMap.get(userId ?? '')?.email ||\n userId ||\n 'Unknown'\n : teams.find((team) => team.id === record.teamId)?.name || record.teamId || 'Unknown',\n kind: isUser ? 'user' : 'team',\n permission: record.permission,\n source: 'Direct grant',\n group: 'Access Grants',\n canRemove: isAdmin,\n onPermissionChange: userId\n ? (permission) =>\n grantScopeAccess.mutate({\n userId,\n permission,\n })\n : undefined,\n onRemove: () => revokeScopeAccess.mutate(record.id),\n });\n }\n return rows;\n }, [\n members,\n scopeAccess,\n userMap,\n teams,\n isAdmin,\n removeTeamMember,\n grantScopeAccess,\n revokeScopeAccess,\n ]);\n\n const memberRows = accessRows.filter((row) => row.group === 'Members');\n const _grantRows = accessRows.filter((row) => row.group === 'Access Grants');\n\n const scopePath = useMemo(() => {\n const path: Team[] = [];\n let current = teams.find((team) => team.id === scopeId) ?? null;\n while (current) {\n path.unshift(current);\n current = current.parentId\n ? (teams.find((team) => team.id === current?.parentId) ?? null)\n : null;\n }\n return path;\n }, [teams, scopeId]);\n\n return (\n <div className=\"flex flex-col h-full overflow-hidden\">\n <div className=\"px-5 py-4 overflow-hidden border-b shrink-0 border-imp-border\">\n <div className=\"flex items-start gap-3\">\n <div className=\"flex items-center justify-center flex-none w-10 h-10 rounded-xl bg-imp-primary/10 text-imp-primary\">\n <Users className=\"w-5 h-5\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <h2 className=\"flex-1 min-w-0 text-base font-semibold truncate\">{scopeName}</h2>\n {isAdmin ? (\n <div className=\"flex items-center gap-1.5\">\n <button\n type=\"button\"\n onClick={() => setShowDeleteConfirm(true)}\n className=\"flex items-center gap-1.5 rounded-md border border-imp-destructive/30 px-3 py-1.5 text-xs font-medium text-imp-destructive transition-colors hover:bg-imp-destructive/10\"\n >\n <Trash2 className=\"w-4 h-4\" /> Delete team\n </button>\n </div>\n ) : null}\n </div>\n <div className=\"flex flex-wrap items-center gap-1 mt-1 text-[11px] text-imp-muted-foreground\">\n <span>Root</span>\n {scopePath.map((team) => (\n <div key={team.id} className=\"flex items-center gap-1\">\n <ChevronRight className=\"w-3 h-3\" />\n <span\n className={team.id === scopeId ? 'font-medium text-imp-foreground' : undefined}\n >\n {team.name}\n </span>\n </div>\n ))}\n </div>\n </div>\n </div>\n <div className=\"flex items-center justify-between\">\n <p className=\"mt-3 text-xs text-imp-muted-foreground\">\n Access applies to all flows inside this team and its child teams.\n </p>\n </div>\n </div>\n\n <div className=\"flex-1 px-5 py-4 overflow-x-hidden overflow-y-auto\">\n <div className=\"space-y-6\">\n <section>\n <div className=\"flex items-center justify-between gap-4\">\n <div className=\"min-w-0\">\n <h3 className=\"text-sm font-semibold text-imp-foreground\">\n Team Role on Child Flows\n </h3>\n <p className=\"mt-0.5 text-xs text-imp-muted-foreground\">\n Base role applied to every flow inside this team.\n </p>\n </div>\n <div className=\"shrink-0\">\n <OptionalRoleSelector\n value={teamRoleRecord?.permission ?? null}\n emptyLabel=\"No team role\"\n onChange={(nextPermission) => {\n if (nextPermission === null) {\n if (teamRoleRecord) {\n revokeScopeAccess.mutate(teamRoleRecord.id);\n }\n return;\n }\n\n grantScopeAccess.mutate({\n teamId: scopeId,\n permission: nextPermission,\n });\n }}\n />\n </div>\n </div>\n </section>\n\n <section className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"text-sm font-semibold text-imp-foreground\">Members</h3>\n {isAdmin ? (\n <button\n type=\"button\"\n onClick={() => setShowMemberDialog(true)}\n className=\"flex items-center gap-1.5 rounded-md border border-imp-border px-3 py-1.5 text-xs font-medium text-imp-muted-foreground transition-colors hover:border-imp-primary/50 hover:text-imp-foreground\"\n >\n <Plus className=\"w-4 h-4\" /> Add Member\n </button>\n ) : null}\n </div>\n <div className=\"overflow-hidden border rounded-xl border-imp-border bg-imp-background/40\">\n <AccessTable rows={memberRows} isLoading={isLoading} emptyLabel=\"No members\" />\n </div>\n </section>\n\n {childTeams.length > 0 ? (\n <section className=\"space-y-2\">\n <h3 className=\"text-sm font-semibold text-imp-foreground\">Sub-teams</h3>\n <div className=\"space-y-2\">\n {childTeams.map((team) => (\n <div\n key={team.id}\n className=\"flex items-center gap-2 px-3 py-2 border rounded-xl border-imp-border bg-imp-background/40\"\n >\n <Users className=\"w-3.5 h-3.5 text-imp-muted-foreground\" />\n <span className=\"flex-1 min-w-0 text-sm font-medium truncate text-imp-foreground\">\n {team.name}\n </span>\n <span className=\"text-[11px] text-imp-muted-foreground\">Child team</span>\n </div>\n ))}\n </div>\n </section>\n ) : null}\n </div>\n </div>\n\n <FormDialog\n open={showGrantDialog}\n onClose={() => setShowGrantDialog(false)}\n title=\"Grant Scope Access\"\n >\n <div className=\"flex flex-col gap-3\">\n <MemberCombobox\n users={users}\n excludeIds={existingScopeUserIds}\n selectedUserIds={grantUserIds}\n onSelect={setGrantUserIds}\n />\n <div className=\"flex items-center gap-2\">\n <RoleSelector value={permission} onChange={setPermission} />\n <button\n type=\"button\"\n onClick={() => {\n if (grantUserIds.length === 0) {\n return;\n }\n for (const userId of grantUserIds) {\n grantScopeAccess.mutate({ userId, permission });\n }\n setGrantUserIds([]);\n setShowGrantDialog(false);\n }}\n disabled={grantUserIds.length === 0 || grantScopeAccess.isPending}\n className=\"ml-auto rounded-md bg-imp-primary px-4 py-2 text-sm font-semibold text-imp-primary-foreground hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n Grant\n </button>\n </div>\n </div>\n </FormDialog>\n\n <FormDialog\n open={showMemberDialog}\n onClose={() => setShowMemberDialog(false)}\n title=\"Add Team Member\"\n >\n <div className=\"flex flex-col gap-3\">\n <MemberCombobox\n users={users}\n excludeIds={existingMemberIds}\n selectedUserIds={memberUserIds}\n onSelect={setMemberUserIds}\n />\n <button\n type=\"button\"\n onClick={() => {\n if (memberUserIds.length === 0) {\n return;\n }\n for (const userId of memberUserIds) {\n addTeamMember.mutate({ userId });\n }\n setMemberUserIds([]);\n setShowMemberDialog(false);\n }}\n disabled={memberUserIds.length === 0 || addTeamMember.isPending}\n className=\"rounded-md bg-imp-primary px-4 py-2 text-sm font-semibold text-imp-primary-foreground hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n Add\n </button>\n </div>\n </FormDialog>\n\n <Dialog\n open={showDeleteConfirm}\n onOpenChange={(open) => !open && setShowDeleteConfirm(false)}\n >\n <DialogContent className=\"max-w-sm border-imp-border bg-imp-background text-imp-foreground sm:max-w-sm\">\n <DialogHeader>\n <DialogTitle className=\"text-sm font-semibold\">Delete team</DialogTitle>\n </DialogHeader>\n <p className=\"text-sm text-imp-muted-foreground\">\n Are you sure you want to delete{' '}\n <strong className=\"text-imp-foreground\">{scopeName}</strong>? Flows directly inside this\n team will move to the parent team when one exists, and this team's access grants will be\n removed.\n </p>\n <DialogFooter className=\"gap-2 sm:gap-0\">\n <button\n type=\"button\"\n onClick={() => setShowDeleteConfirm(false)}\n className=\"rounded-md border border-imp-border px-3 py-1.5 text-xs font-medium text-imp-muted-foreground hover:text-imp-foreground\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={() => {\n deleteScope.mutate(scopeId);\n setShowDeleteConfirm(false);\n }}\n className=\"rounded-md bg-red-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-red-700\"\n >\n Delete\n </button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n );\n}\n","import { useRef, useState } from 'react';\nimport { User, Users, X } from 'lucide-react';\nimport type { Team } from '../../../shared/types';\nimport type { AuthUser, PrincipalSelection } from './types';\n\nexport function PrincipalCombobox({\n users,\n teams,\n excludeUserIds,\n excludeTeamIds,\n selections,\n onSelect,\n}: {\n users: AuthUser[];\n teams: Team[];\n excludeUserIds: Set<string | null | undefined>;\n excludeTeamIds: Set<string | null | undefined>;\n selections: PrincipalSelection[];\n onSelect: (selections: PrincipalSelection[]) => void;\n}) {\n const [query, setQuery] = useState('');\n const [open, setOpen] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const selectedUserIds = new Set(selections.filter((s) => s.type === 'user').map((s) => s.id));\n const selectedTeamIds = new Set(selections.filter((s) => s.type === 'team').map((s) => s.id));\n\n const filteredUsers = users.filter((user) => {\n if (excludeUserIds.has(user.id)) {\n return false;\n }\n if (selectedUserIds.has(user.id)) {\n return false;\n }\n const haystack = `${user.name || ''} ${user.email || ''} ${user.id}`.toLowerCase();\n return haystack.includes(query.toLowerCase());\n });\n\n const filteredTeams = teams.filter((team) => {\n if (excludeTeamIds.has(team.id)) {\n return false;\n }\n if (selectedTeamIds.has(team.id)) {\n return false;\n }\n const haystack = `${team.name} ${team.description || ''}`.toLowerCase();\n return haystack.includes(query.toLowerCase());\n });\n\n const toggle = (sel: PrincipalSelection) => {\n const exists = selections.some((s) => s.type === sel.type && s.id === sel.id);\n onSelect(\n exists\n ? selections.filter((s) => !(s.type === sel.type && s.id === sel.id))\n : [...selections, sel],\n );\n };\n\n const getLabel = (sel: PrincipalSelection): string => {\n if (sel.type === 'user') {\n const user = users.find((u) => u.id === sel.id);\n return user?.name || user?.email || sel.id;\n }\n return teams.find((t) => t.id === sel.id)?.name || sel.id;\n };\n\n return (\n <div\n ref={containerRef}\n className=\"relative\"\n onBlur={(e) => {\n if (!containerRef.current?.contains(e.relatedTarget as Node)) {\n setOpen(false);\n }\n }}\n >\n <div\n className=\"flex min-h-[2.5rem] w-full cursor-text flex-wrap gap-1.5 rounded-md border border-imp-border bg-imp-background px-2 py-1.5 focus-within:border-imp-primary/50\"\n onClick={() => setOpen(true)}\n >\n {selections.map((sel) => (\n <span\n key={`${sel.type}:${sel.id}`}\n className=\"inline-flex items-center gap-1 rounded-md border border-imp-border bg-imp-muted px-2 py-0.5 text-xs font-medium text-imp-foreground\"\n >\n {sel.type === 'user' ? (\n <User className=\"h-3 w-3 shrink-0 text-imp-muted-foreground\" />\n ) : (\n <Users className=\"h-3 w-3 shrink-0 text-imp-muted-foreground\" />\n )}\n <span className=\"max-w-[140px] truncate\">{getLabel(sel)}</span>\n <button\n type=\"button\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={(e) => {\n e.stopPropagation();\n toggle(sel);\n }}\n className=\"ml-0.5 text-imp-muted-foreground hover:text-imp-foreground\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </span>\n ))}\n <input\n value={query}\n onChange={(e) => {\n setQuery(e.target.value);\n setOpen(true);\n }}\n onFocus={() => setOpen(true)}\n placeholder={selections.length === 0 ? 'Search users or teams…' : 'Add more…'}\n className=\"min-w-[120px] flex-1 bg-transparent text-sm outline-none placeholder:text-imp-muted-foreground\"\n />\n </div>\n {open && (\n <div className=\"absolute left-0 z-20 mt-1 w-full overflow-y-auto rounded-md border border-imp-border bg-imp-background shadow-lg top-full max-h-52\">\n {filteredTeams.length === 0 && filteredUsers.length === 0 ? (\n <div className=\"px-3 py-2 text-xs text-imp-muted-foreground\">\n {query ? 'No matches.' : 'No more users or teams to add.'}\n </div>\n ) : (\n <>\n {filteredTeams.length > 0 && (\n <>\n <div className=\"px-3 py-1 text-[10px] font-medium uppercase tracking-wider text-imp-muted-foreground\">\n Teams\n </div>\n {filteredTeams.map((team) => (\n <button\n key={team.id}\n type=\"button\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n toggle({ type: 'team', id: team.id });\n setQuery('');\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-imp-muted/50\"\n >\n <Users className=\"h-4 w-4 shrink-0 text-imp-muted-foreground\" />\n <span className=\"truncate font-medium\">{team.name}</span>\n </button>\n ))}\n </>\n )}\n {filteredUsers.length > 0 && (\n <>\n <div className=\"px-3 py-1 text-[10px] font-medium uppercase tracking-wider text-imp-muted-foreground\">\n Users\n </div>\n {filteredUsers.map((user) => (\n <button\n key={user.id}\n type=\"button\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n toggle({ type: 'user', id: user.id });\n setQuery('');\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-imp-muted/50\"\n >\n <User className=\"h-4 w-4 shrink-0 text-imp-muted-foreground\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate font-medium\">\n {user.name || user.email || user.id}\n </div>\n {user.name && user.email && (\n <div className=\"truncate text-xs text-imp-muted-foreground\">\n {user.email}\n </div>\n )}\n </div>\n </button>\n ))}\n </>\n )}\n </>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useMemo, useState } from 'react';\nimport { ChevronRight, ExternalLink, Plus, Workflow } from 'lucide-react';\nimport { useGrantFlowAccess, useRevokeFlowAccess } from '../../hooks/useFlowAccess';\nimport { useEffectiveFlowAccess } from '../../hooks/useScopes';\nimport type { FlowAccessPermission, Team } from '../../../shared/types';\nimport type { AccessRow, AuthUser, PrincipalSelection } from './types';\nimport { AccessTable, RoleSelector } from './AccessTable';\nimport { FormDialog } from './FormDialog';\nimport { PrincipalCombobox } from './PrincipalCombobox';\n\nexport function FlowDetailPanel({\n flowId,\n flowName,\n users,\n userMap,\n teams,\n isAdmin,\n}: {\n flowId: string;\n flowName: string;\n users: AuthUser[];\n userMap: Map<string, AuthUser>;\n teams: Team[];\n isAdmin: boolean;\n}) {\n const effectiveFlowAccessQuery = useEffectiveFlowAccess(flowId);\n const grantFlowAccess = useGrantFlowAccess(flowId);\n const revokeFlowAccess = useRevokeFlowAccess(flowId);\n const [showGrantDialog, setShowGrantDialog] = useState(false);\n const [principalSelections, setPrincipalSelections] = useState<PrincipalSelection[]>([]);\n const [permission, setPermission] = useState<FlowAccessPermission>('viewer');\n\n const effectiveRecords = effectiveFlowAccessQuery.data?.records ?? [];\n const existingDirectUserIds = new Set(\n effectiveRecords\n .filter((record) => record.source === 'direct' && record.userId)\n .map((record) => record.userId),\n );\n const existingDirectTeamIds = new Set(\n effectiveRecords\n .filter((record) => record.source === 'direct' && record.teamId)\n .map((record) => record.teamId),\n );\n const owningTeam =\n teams.find((team) => team.id === effectiveFlowAccessQuery.data?.scopeId) ?? null;\n const scopePath = useMemo(() => {\n const path: Team[] = [];\n let current = owningTeam;\n\n while (current) {\n path.unshift(current);\n current = current.parentId\n ? (teams.find((team) => team.id === current?.parentId) ?? null)\n : null;\n }\n\n return path;\n }, [owningTeam, teams]);\n\n const accessRows = useMemo(() => {\n const rows: AccessRow[] = effectiveRecords.map((record) => {\n const isUser = !!record.userId;\n const userId = record.userId ?? null;\n const teamId = record.teamId ?? null;\n\n return {\n id: `${record.source}:${record.id}`,\n label: isUser\n ? userMap.get(userId ?? '')?.name ||\n userMap.get(userId ?? '')?.email ||\n userId ||\n 'Unknown'\n : teams.find((team) => team.id === teamId)?.name || teamId || 'Unknown',\n kind: isUser ? 'user' : 'team',\n permission: record.permission,\n source: record.source === 'direct' ? 'Direct grant' : `via ${record.scopeName || 'team'}`,\n group: record.source === 'direct' ? 'Direct' : 'Inherited',\n canRemove: record.source === 'direct' && isAdmin,\n onPermissionChange:\n record.source === 'direct'\n ? (permission) =>\n grantFlowAccess.mutate({\n ...(userId ? { userId } : teamId ? { teamId } : {}),\n permission,\n })\n : undefined,\n onRemove: () => revokeFlowAccess.mutate(record.id),\n };\n });\n\n rows.sort((a, b) => {\n const aIsDirect = a.source === 'Direct grant' ? 1 : 0;\n const bIsDirect = b.source === 'Direct grant' ? 1 : 0;\n return bIsDirect - aIsDirect;\n });\n\n return rows;\n }, [effectiveRecords, userMap, teams, isAdmin, grantFlowAccess, revokeFlowAccess]);\n\n const directRows = accessRows.filter((row) => row.group === 'Direct');\n const inheritedRows = accessRows.filter((row) => row.group === 'Inherited');\n\n const openFlow = () => {\n const path = window.location.pathname;\n const accessIdx = path.lastIndexOf('/access');\n const basePath = accessIdx >= 0 ? path.slice(0, accessIdx) : path;\n window.open(`${basePath}/flow/${flowId}`, '_blank');\n };\n\n return (\n <div className=\"flex flex-col h-full overflow-hidden\">\n <div className=\"px-5 py-4 overflow-hidden border-b shrink-0 border-imp-border\">\n <div className=\"flex items-start gap-3\">\n <div className=\"flex items-center justify-center flex-none w-10 h-10 rounded-xl bg-imp-primary/10 text-imp-primary\">\n <Workflow className=\"w-5 h-5\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <h2 className=\"flex-1 min-w-0 text-base font-semibold truncate\">{flowName}</h2>\n </div>\n <div className=\"mt-1 flex flex-wrap items-center gap-1 text-[11px] text-imp-muted-foreground\">\n <span>Root</span>\n {scopePath.map((team) => (\n <div key={team.id} className=\"flex items-center gap-1\">\n <ChevronRight className=\"w-3 h-3\" />\n <span>{team.name}</span>\n </div>\n ))}\n <div className=\"flex items-center gap-1\">\n <ChevronRight className=\"w-3 h-3\" />\n <span className=\"font-medium text-imp-foreground\">{flowName}</span>\n </div>\n </div>\n </div>\n <div className=\"flex items-center gap-1.5\">\n <button\n type=\"button\"\n onClick={openFlow}\n className=\"flex items-center gap-1.5 rounded-md border border-imp-border px-3 py-1.5 text-xs font-medium text-imp-muted-foreground transition-colors hover:border-imp-primary/50 hover:text-imp-foreground\"\n >\n <ExternalLink className=\"w-4 h-4\" /> Open in Editor\n </button>\n </div>\n </div>\n <p className=\"mt-3 text-xs text-imp-muted-foreground\">\n All principals with access and how they got it.\n </p>\n </div>\n\n <div className=\"flex-1 px-5 py-4 overflow-x-hidden overflow-y-auto\">\n <div className=\"space-y-6\">\n <section className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"text-sm font-semibold text-imp-foreground\">Direct Access</h3>\n {isAdmin ? (\n <button\n type=\"button\"\n onClick={() => setShowGrantDialog(true)}\n className=\"flex items-center gap-1.5 rounded-md border border-imp-border px-3 py-1.5 text-xs font-medium text-imp-muted-foreground transition-colors hover:border-imp-primary/50 hover:text-imp-foreground\"\n >\n <Plus className=\"w-4 h-4\" /> Grant Access\n </button>\n ) : null}\n </div>\n <div className=\"overflow-hidden border rounded-xl border-imp-border bg-imp-background/40\">\n <AccessTable\n rows={directRows}\n isLoading={effectiveFlowAccessQuery.isLoading}\n emptyLabel=\"No direct access assigned\"\n />\n </div>\n </section>\n\n <section className=\"space-y-2\">\n <h3 className=\"text-sm font-semibold text-imp-foreground\">Inherited Access</h3>\n <div className=\"overflow-hidden border rounded-xl border-imp-border bg-imp-background/40\">\n <AccessTable\n rows={inheritedRows}\n isLoading={effectiveFlowAccessQuery.isLoading}\n emptyLabel=\"No inherited access\"\n />\n </div>\n </section>\n </div>\n </div>\n\n <FormDialog\n open={showGrantDialog}\n onClose={() => setShowGrantDialog(false)}\n title=\"Grant Flow Access\"\n >\n <div className=\"flex flex-col gap-3\">\n <PrincipalCombobox\n users={users}\n teams={teams}\n excludeUserIds={existingDirectUserIds}\n excludeTeamIds={existingDirectTeamIds}\n selections={principalSelections}\n onSelect={setPrincipalSelections}\n />\n <div className=\"flex items-center gap-2\">\n <RoleSelector value={permission} onChange={setPermission} />\n <button\n type=\"button\"\n onClick={() => {\n if (principalSelections.length === 0) {\n return;\n }\n for (const sel of principalSelections) {\n grantFlowAccess.mutate({\n ...(sel.type === 'user' ? { userId: sel.id } : { teamId: sel.id }),\n permission,\n });\n }\n setPrincipalSelections([]);\n setShowGrantDialog(false);\n }}\n disabled={principalSelections.length === 0 || grantFlowAccess.isPending}\n className=\"ml-auto rounded-md bg-imp-primary px-4 py-2 text-sm font-semibold text-imp-primary-foreground hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n Grant\n </button>\n </div>\n </div>\n </FormDialog>\n </div>\n );\n}\n","import { Move, User, Users, X } from 'lucide-react';\nimport { useMoveFlow } from '../../hooks/useScopes';\nimport { useUpdateTeam } from '../../hooks/useTeams';\nimport type { MovePreviewResponse } from '../../../shared/types';\nimport type { PendingMove } from './types';\nimport { getPermissionBadgeClasses } from './types';\n\nexport function MoveConfirmationDialog({\n pendingMove,\n preview,\n error,\n onClose,\n}: {\n pendingMove: PendingMove | null;\n preview: MovePreviewResponse | null;\n error: string | null;\n onClose: () => void;\n}) {\n const moveFlow = useMoveFlow(pendingMove?.type === 'flow' ? pendingMove.id : '');\n const reparentScope = useUpdateTeam(pendingMove?.type === 'scope' ? pendingMove.id : '');\n\n const isSubmitting = moveFlow.isPending || reparentScope.isPending;\n\n const handleConfirm = async () => {\n if (!pendingMove) {\n return;\n }\n if (pendingMove.type === 'flow') {\n await moveFlow.mutateAsync(pendingMove.targetScopeId);\n } else {\n await reparentScope.mutateAsync({ parentId: pendingMove.targetScopeId });\n }\n onClose();\n };\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/35\">\n <div className=\"w-full max-w-lg rounded-xl border border-imp-border bg-imp-background shadow-[var(--imp-shadow-floating)]\">\n <div className=\"flex items-center justify-between px-5 py-4 border-b border-imp-border\">\n <div>\n <div className=\"flex items-center gap-2 text-sm font-semibold text-imp-foreground\">\n <Move className=\"w-4 h-4 text-imp-primary\" />\n Confirm Move\n </div>\n <p className=\"mt-1 text-xs text-imp-muted-foreground\">\n Review the access impact before applying this hierarchy change.\n </p>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1 rounded text-imp-muted-foreground hover:text-imp-foreground\"\n >\n <X className=\"w-4 h-4\" />\n </button>\n </div>\n\n <div className=\"px-5 py-4 space-y-4 text-sm\">\n {error ? (\n <div className=\"px-3 py-2 text-red-700 border border-red-300 rounded-lg bg-red-50 dark:border-red-900 dark:bg-red-950/20 dark:text-red-300\">\n {error}\n </div>\n ) : !preview ? (\n <div className=\"px-3 py-4 text-center border rounded-lg border-imp-border bg-imp-card text-imp-muted-foreground\">\n Calculating impact…\n </div>\n ) : (\n <>\n <div className=\"px-3 py-3 border rounded-lg border-imp-border bg-imp-card\">\n <div className=\"font-medium text-imp-foreground\">\n Move \"{preview.item.name}\" to{' '}\n {preview.target.path.length > 0 ? preview.target.path.join(' / ') : 'Top level'}\n </div>\n <div className=\"mt-1 text-xs text-imp-muted-foreground\">\n {preview.affectedFlows} flow{preview.affectedFlows === 1 ? '' : 's'} affected\n </div>\n </div>\n\n <div>\n <div className=\"mb-2 text-xs font-medium tracking-wider uppercase text-imp-muted-foreground\">\n Access Changes\n </div>\n <div className=\"p-2 space-y-1 overflow-y-auto border rounded-lg max-h-56 border-imp-border bg-imp-card\">\n {preview.accessChanges.gained.length === 0 ? (\n <div className=\"px-2 py-2 text-xs text-imp-muted-foreground\">\n No new principals gain access from this move.\n </div>\n ) : (\n preview.accessChanges.gained.map((entry) => (\n <div\n key={`${entry.source}-${entry.name}`}\n className=\"flex items-center gap-2 rounded-md px-2 py-1.5 text-xs\"\n >\n <div className=\"flex items-center justify-center w-6 h-6 rounded-full shrink-0 bg-imp-primary/10\">\n {entry.userId ? (\n <User className=\"w-3 h-3 text-imp-primary\" />\n ) : (\n <Users className=\"w-3 h-3 text-imp-primary\" />\n )}\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"font-medium truncate\">{entry.name}</div>\n <div className=\"truncate text-[10px] text-imp-muted-foreground\">\n {entry.source}\n </div>\n </div>\n <span\n className={`rounded px-1.5 py-0.5 text-[10px] font-medium ${getPermissionBadgeClasses(entry.permission)}`}\n >\n {entry.permission}\n </span>\n </div>\n ))\n )}\n </div>\n <p className=\"mt-2 text-xs text-imp-muted-foreground\">\n {preview.accessChanges.unchanged} access grant\n {preview.accessChanges.unchanged === 1 ? '' : 's'} remain unchanged.\n </p>\n </div>\n </>\n )}\n </div>\n\n <div className=\"flex items-center justify-end gap-2 px-5 py-4 border-t border-imp-border\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"rounded border border-imp-border px-3 py-1.5 text-sm text-imp-muted-foreground hover:text-imp-foreground\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={handleConfirm}\n disabled={!preview || isSubmitting || !!error}\n className=\"rounded bg-imp-primary px-3 py-1.5 text-sm font-medium text-imp-primary-foreground hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n {isSubmitting ? 'Applying…' : `Move ${pendingMove?.type === 'scope' ? 'Team' : 'Flow'}`}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","import { create } from 'zustand';\nimport type { MovePreviewResponse, ScopeTreeNode } from '../../shared/types';\nimport type { PendingMove, SelectedItem } from '../components/access-control/types';\n\nexport type HierarchyDragItem = {\n type: 'scope' | 'flow';\n id: string;\n name: string;\n /** Current parent scope id, or null if at root */\n parentId: string | null;\n};\n\ninterface AccessControlState {\n // Selection\n selected: SelectedItem | null;\n setSelected: (item: SelectedItem | null) => void;\n\n // Tree\n expandedNodes: Set<string>;\n setExpandedNodes: (nodes: Set<string>) => void;\n toggleNode: (scopeId: string) => void;\n expandAll: (ids: string[]) => void;\n\n // Search\n search: string;\n setSearch: (q: string) => void;\n\n // New team creation\n showNewTeam: boolean;\n setShowNewTeam: (show: boolean) => void;\n newTeamName: string;\n setNewTeamName: (name: string) => void;\n\n // Drag-and-drop\n draggedItem: HierarchyDragItem | null;\n dropTarget: string | null; // scope id or 'root', null when nothing hovered\n startDrag: (item: HierarchyDragItem) => void;\n endDrag: () => void;\n /**\n * Called on dragover for a specific target.\n * Returns true if the drop is valid (caller should call event.preventDefault).\n */\n setDropTarget: (targetId: string | null) => void;\n\n // Move flow\n pendingMove: PendingMove | null;\n movePreview: MovePreviewResponse | null;\n moveError: string | null;\n setPendingMove: (move: PendingMove | null) => void;\n setMovePreview: (preview: MovePreviewResponse | null) => void;\n setMoveError: (error: string | null) => void;\n clearMove: () => void;\n}\n\nexport const useAccessControlStore = create<AccessControlState>()((set) => ({\n // Selection\n selected: null,\n setSelected: (item) => set({ selected: item }),\n\n // Tree\n expandedNodes: new Set(),\n setExpandedNodes: (nodes) => set({ expandedNodes: nodes }),\n toggleNode: (scopeId) =>\n set((state) => {\n const next = new Set(state.expandedNodes);\n if (next.has(scopeId)) {\n next.delete(scopeId);\n } else {\n next.add(scopeId);\n }\n return { expandedNodes: next };\n }),\n expandAll: (ids) => set({ expandedNodes: new Set(ids) }),\n\n // Search\n search: '',\n setSearch: (q) => set({ search: q }),\n\n // New team\n showNewTeam: false,\n setShowNewTeam: (show) => set({ showNewTeam: show }),\n newTeamName: '',\n setNewTeamName: (name) => set({ newTeamName: name }),\n\n // Drag-and-drop\n draggedItem: null,\n dropTarget: null,\n startDrag: (item) => set({ draggedItem: item, dropTarget: null }),\n endDrag: () => set({ draggedItem: null, dropTarget: null }),\n setDropTarget: (targetId) => set({ dropTarget: targetId }),\n\n // Move\n pendingMove: null,\n movePreview: null,\n moveError: null,\n setPendingMove: (move) => set({ pendingMove: move }),\n setMovePreview: (preview) => set({ movePreview: preview }),\n setMoveError: (error) => set({ moveError: error }),\n clearMove: () => set({ pendingMove: null, movePreview: null, moveError: null }),\n}));\n\n// ─── Drag-and-drop helpers ───────────────────────────────────────────────────\n\nfunction collectScopeIds(scopes: ScopeTreeNode[]): string[] {\n return scopes.flatMap((scope) => [scope.id, ...collectScopeIds(scope.children)]);\n}\n\nfunction findScopeNode(scopes: ScopeTreeNode[], scopeId: string): ScopeTreeNode | null {\n for (const scope of scopes) {\n if (scope.id === scopeId) {\n return scope;\n }\n const child = findScopeNode(scope.children, scopeId);\n if (child) {\n return child;\n }\n }\n return null;\n}\n\nfunction scopeContains(scope: ScopeTreeNode, potentialChildId: string): boolean {\n for (const child of scope.children) {\n if (child.id === potentialChildId || scopeContains(child, potentialChildId)) {\n return true;\n }\n }\n return false;\n}\n\nexport function isDescendantScope(\n scopes: ScopeTreeNode[],\n draggedScopeId: string,\n potentialTargetId: string,\n): boolean {\n const draggedScope = findScopeNode(scopes, draggedScopeId);\n if (!draggedScope) {\n return false;\n }\n return scopeContains(draggedScope, potentialTargetId);\n}\n\nexport { collectScopeIds };\n\n/**\n * Returns true if dropping `dragged` onto `targetId` is a valid move.\n * targetId of null means \"move to root\".\n */\nexport function canDropOnTarget(\n dragged: HierarchyDragItem,\n targetId: string | null,\n allScopes: ScopeTreeNode[],\n): boolean {\n // Can't drop a scope onto itself\n if (dragged.type === 'scope' && dragged.id === targetId) {\n return false;\n }\n // Can't drop a scope onto one of its own descendants\n if (\n dragged.type === 'scope' &&\n targetId !== null &&\n isDescendantScope(allScopes, dragged.id, targetId)\n ) {\n return false;\n }\n // No-op: item is already in this scope\n if (dragged.parentId === targetId) {\n return false;\n }\n return true;\n}\n","import { useCallback, useEffect, useMemo } from 'react';\nimport { clsx } from 'clsx';\nimport {\n ChevronDown,\n ChevronRight,\n FolderInput,\n GripVertical,\n Plus,\n Search,\n Shield,\n Users,\n Workflow,\n} from 'lucide-react';\nimport { PageLayout } from '@invect/ui';\nimport { useRbac } from '../../providers/RbacProvider';\nimport { useTeams, useCreateTeam } from '../../hooks/useTeams';\nimport { useScopeTree, usePreviewMove } from '../../hooks/useScopes';\nimport type { FlowSummary, ScopeTreeNode } from '../../../shared/types';\nimport type { AuthUser, SelectedItem } from './types';\nimport { formatPermissionLabel, getPermissionBadgeClasses } from './types';\nimport { useUsers } from './useUsers';\nimport { ScopeDetailPanel } from './ScopeDetailPanel';\nimport { FlowDetailPanel } from './FlowDetailPanel';\nimport { MoveConfirmationDialog } from './MoveConfirmationDialog';\nimport {\n useAccessControlStore,\n canDropOnTarget,\n collectScopeIds,\n type HierarchyDragItem,\n} from '../../stores/accessControlStore';\n\n// ─── Tree helpers ─────────────────────────────────────────────────────────────\n\nfunction findScopeNode(scopes: ScopeTreeNode[], scopeId: string): ScopeTreeNode | null {\n for (const scope of scopes) {\n if (scope.id === scopeId) {\n return scope;\n }\n const child = findScopeNode(scope.children, scopeId);\n if (child) {\n return child;\n }\n }\n return null;\n}\n\nfunction filterScopes(scopes: ScopeTreeNode[], query: string): ScopeTreeNode[] {\n return scopes.reduce<ScopeTreeNode[]>((acc, scope) => {\n const matchesScope =\n scope.name.toLowerCase().includes(query) ||\n (scope.description?.toLowerCase().includes(query) ?? false);\n const matchingChildren = filterScopes(scope.children, query);\n const matchingFlows = scope.flows.filter((flow) => flow.name.toLowerCase().includes(query));\n\n if (matchesScope || matchingChildren.length > 0 || matchingFlows.length > 0) {\n acc.push({ ...scope, children: matchingChildren, flows: matchingFlows });\n }\n return acc;\n }, []);\n}\n\nfunction findSelectedName(\n scopes: ScopeTreeNode[],\n flows: FlowSummary[],\n selected: SelectedItem | null,\n): string | null {\n if (!selected) {\n return null;\n }\n\n if (selected.kind === 'team') {\n return findScopeNode(scopes, selected.id)?.name ?? selected.name;\n }\n\n const stack = [...flows];\n const scopeStack = [...scopes];\n while (scopeStack.length > 0) {\n const current = scopeStack.pop();\n if (!current) {\n break;\n }\n stack.push(...current.flows);\n scopeStack.push(...current.children);\n }\n return stack.find((flow) => flow.id === selected.id)?.name ?? selected.name;\n}\n\n// ─── FlowTreeRow ──────────────────────────────────────────────────────────────\n\nfunction FlowTreeRow({\n flow,\n isSelected,\n onSelect,\n}: {\n flow: FlowSummary;\n isSelected: boolean;\n onSelect: (flow: FlowSummary) => void;\n}) {\n const { draggedItem, startDrag, endDrag } = useAccessControlStore();\n const isDragging = draggedItem?.type === 'flow' && draggedItem.id === flow.id;\n\n return (\n <div\n draggable\n onDragStart={(event) => {\n event.dataTransfer.effectAllowed = 'move';\n startDrag({ type: 'flow', id: flow.id, name: flow.name, parentId: flow.scopeId ?? null });\n }}\n onDragEnd={endDrag}\n onClick={() => onSelect(flow)}\n className={clsx(\n 'group flex cursor-pointer items-center gap-2 rounded-md px-4 py-1.5 transition-colors',\n 'hover:bg-imp-muted/50',\n isDragging && 'opacity-40',\n isSelected && 'bg-imp-primary/10 text-imp-primary ring-1 ring-imp-primary/30',\n )}\n >\n <Workflow\n className={clsx(\n 'h-4 w-4 shrink-0',\n isSelected ? 'text-imp-primary' : 'text-imp-muted-foreground',\n )}\n />\n <span className=\"flex-1 min-w-0 text-sm font-medium truncate\">{flow.name}</span>\n <GripVertical className=\"h-3.5 w-3.5 shrink-0 text-imp-muted-foreground/60 opacity-0 transition-opacity group-hover:opacity-100\" />\n </div>\n );\n}\n\n// ─── ScopeTreeRow ─────────────────────────────────────────────────────────────\n\nfunction ScopeTreeRow({\n scope,\n allScopes,\n depth,\n onSelectScope,\n onSelectFlow,\n onTriggerMove,\n}: {\n scope: ScopeTreeNode;\n allScopes: ScopeTreeNode[];\n depth: number;\n onSelectScope: (scope: ScopeTreeNode) => void;\n onSelectFlow: (flow: FlowSummary) => void;\n onTriggerMove: (item: HierarchyDragItem, targetId: string | null) => void;\n}) {\n const {\n draggedItem,\n dropTarget,\n selected,\n expandedNodes,\n startDrag,\n endDrag,\n setDropTarget,\n toggleNode,\n } = useAccessControlStore();\n\n const isExpanded = expandedNodes.has(scope.id);\n const isSelected = selected?.kind === 'team' && selected.id === scope.id;\n const isDragging = draggedItem?.type === 'scope' && draggedItem.id === scope.id;\n const hasChildren = scope.children.length > 0 || scope.flows.length > 0;\n\n const canDrop = draggedItem !== null && canDropOnTarget(draggedItem, scope.id, allScopes);\n const isDropTarget = dropTarget === scope.id && canDrop;\n\n const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {\n if (!draggedItem || !canDrop) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n if (dropTarget !== scope.id) {\n setDropTarget(scope.id);\n }\n };\n\n // Use relatedTarget to avoid clearing the drop highlight when entering a child node.\n const handleDragLeave = (event: React.DragEvent<HTMLDivElement>) => {\n const related = event.relatedTarget as Node | null;\n if (related && event.currentTarget.contains(related)) {\n return;\n }\n if (dropTarget === scope.id) {\n setDropTarget(null);\n }\n };\n\n const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n event.stopPropagation();\n if (!draggedItem || !canDrop) {\n return;\n }\n onTriggerMove(draggedItem, scope.id);\n };\n\n return (\n <div onDragOver={handleDragOver} onDragLeave={handleDragLeave} onDrop={handleDrop}>\n <div\n draggable\n onDragStart={(event) => {\n event.dataTransfer.effectAllowed = 'move';\n startDrag({\n type: 'scope',\n id: scope.id,\n name: scope.name,\n parentId: scope.parentId ?? null,\n });\n }}\n onDragEnd={endDrag}\n onClick={() => onSelectScope(scope)}\n className={clsx(\n 'group flex cursor-pointer items-center gap-2 rounded-xl px-3 py-2 transition-colors',\n isDragging && 'opacity-40',\n isDropTarget && 'ring-2 ring-imp-primary/40 bg-imp-primary/5',\n isSelected ? 'text-imp-primary ring-1 ring-imp-primary/30' : 'hover:bg-accent',\n )}\n >\n {hasChildren ? (\n <button\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n toggleNode(scope.id);\n }}\n className=\"rounded p-0.5 text-imp-muted-foreground hover:bg-imp-muted\"\n >\n {isExpanded ? (\n <ChevronDown className=\"w-4 h-4\" />\n ) : (\n <ChevronRight className=\"w-4 h-4\" />\n )}\n </button>\n ) : (\n <span className=\"w-5 shrink-0\" />\n )}\n <Users\n className={clsx(\n 'h-4 w-4 shrink-0',\n isSelected ? 'text-imp-primary' : 'text-imp-muted-foreground',\n )}\n />\n <span className=\"flex-1 min-w-0 text-sm font-medium truncate\">{scope.name}</span>\n {scope.teamPermission ? (\n <span\n className={clsx(\n 'inline-flex shrink-0 rounded-full border px-2 py-0.5 text-[10px] font-medium',\n getPermissionBadgeClasses(scope.teamPermission),\n )}\n >\n {formatPermissionLabel(scope.teamPermission)}\n </span>\n ) : null}\n <GripVertical className=\"h-3.5 w-3.5 shrink-0 text-imp-muted-foreground/60 opacity-0 transition-opacity group-hover:opacity-100\" />\n </div>\n\n {isExpanded ? (\n <div className=\"space-y-1 border-l border-imp-border\" style={{ marginLeft: '22px' }}>\n {scope.flows.map((flow) => (\n <FlowTreeRow\n key={flow.id}\n flow={flow}\n isSelected={selected?.kind === 'flow' && selected.id === flow.id}\n onSelect={onSelectFlow}\n />\n ))}\n {scope.children.map((child) => (\n <ScopeTreeRow\n key={child.id}\n scope={child}\n allScopes={allScopes}\n depth={depth + 1}\n onSelectScope={onSelectScope}\n onSelectFlow={onSelectFlow}\n onTriggerMove={onTriggerMove}\n />\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n\nconst EMPTY_SCOPES: ScopeTreeNode[] = [];\nconst EMPTY_FLOWS: FlowSummary[] = [];\n\nexport function AccessControlPage() {\n const { isAuthenticated, checkPermission } = useRbac();\n const isAdmin = isAuthenticated && checkPermission('admin:*');\n\n const users = useUsers();\n const userMap = useMemo(() => {\n const map = new Map<string, AuthUser>();\n for (const user of users) {\n map.set(user.id, user);\n }\n return map;\n }, [users]);\n\n const teamsQuery = useTeams();\n const teams = teamsQuery.data?.teams ?? [];\n const scopeTreeQuery = useScopeTree();\n const createTeam = useCreateTeam();\n const previewMove = usePreviewMove();\n\n const {\n selected,\n setSelected,\n search,\n setSearch,\n expandedNodes,\n expandAll,\n showNewTeam,\n setShowNewTeam,\n newTeamName,\n setNewTeamName,\n draggedItem,\n dropTarget,\n setDropTarget,\n endDrag,\n pendingMove,\n setPendingMove,\n movePreview,\n setMovePreview,\n moveError,\n setMoveError,\n clearMove,\n } = useAccessControlStore();\n\n const scopes = scopeTreeQuery.data?.scopes ?? EMPTY_SCOPES;\n const unscopedFlows = scopeTreeQuery.data?.unscopedFlows ?? EMPTY_FLOWS;\n\n // Auto-expand everything when tree first loads\n useEffect(() => {\n if (scopes.length > 0 && expandedNodes.size === 0) {\n expandAll(collectScopeIds(scopes));\n }\n }, [scopes]); // expanding on load — intentionally tracks scopes only\n\n useEffect(() => {\n scopeTreeQuery.refetch();\n }, []); // fires once on mount\n\n const normalizedSearch = search.trim().toLowerCase();\n const filteredScopes = useMemo(\n () => (normalizedSearch ? filterScopes(scopes, normalizedSearch) : scopes),\n [scopes, normalizedSearch],\n );\n const filteredUnscopedFlows = useMemo(\n () =>\n normalizedSearch\n ? unscopedFlows.filter((f) => f.name.toLowerCase().includes(normalizedSearch))\n : unscopedFlows,\n [unscopedFlows, normalizedSearch],\n );\n\n const selectedName = useMemo(\n () => findSelectedName(scopes, unscopedFlows, selected),\n [scopes, unscopedFlows, selected],\n );\n\n const hasTreeItems = filteredScopes.length > 0 || filteredUnscopedFlows.length > 0;\n\n // Called when a valid drop lands on a target scope (or null = root)\n const handleTriggerMove = useCallback(\n async (item: HierarchyDragItem, targetScopeId: string | null) => {\n endDrag();\n\n if (!canDropOnTarget(item, targetScopeId, scopes)) {\n return;\n }\n\n setPendingMove({ type: item.type, id: item.id, name: item.name, targetScopeId });\n setMovePreview(null);\n setMoveError(null);\n\n try {\n const preview = await previewMove.mutateAsync({\n type: item.type,\n id: item.id,\n targetScopeId,\n });\n setMovePreview(preview);\n } catch (err) {\n setMoveError(err instanceof Error ? err.message : 'Failed to preview move');\n }\n },\n [scopes, endDrag, previewMove, setPendingMove, setMovePreview, setMoveError],\n );\n\n if (!isAuthenticated) {\n return (\n <PageLayout\n title=\"Access Control\"\n subtitle=\"Manage team hierarchy and flow-level access grants.\"\n icon={Shield}\n >\n <p className=\"text-sm text-imp-muted-foreground\">Please sign in to access this page.</p>\n </PageLayout>\n );\n }\n\n const isLoading = scopeTreeQuery.isLoading;\n\n return (\n <PageLayout\n title=\"Access Control\"\n subtitle=\"Manage team hierarchy and flow-level access grants.\"\n icon={Shield}\n >\n {/* Search + New Team */}\n <div className=\"flex items-center gap-2\">\n <div className=\"relative flex-1 max-w-sm\">\n <Search className=\"absolute w-3.5 h-3.5 pointer-events-none left-3 top-1/2 -translate-y-1/2 text-imp-muted-foreground\" />\n <input\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n placeholder=\"Search teams and flows…\"\n className=\"w-full py-2 pr-3 text-sm border rounded-lg outline-none pl-9 border-imp-border bg-imp-background placeholder:text-imp-muted-foreground focus:border-imp-primary/50\"\n />\n </div>\n {isAdmin ? (\n showNewTeam ? (\n <div className=\"flex items-center gap-1.5\">\n <input\n value={newTeamName}\n onChange={(event) => setNewTeamName(event.target.value)}\n placeholder=\"Team name\"\n className=\"px-2.5 py-2 text-sm border rounded-lg border-imp-border bg-imp-background\"\n autoFocus\n onKeyDown={(event) => {\n if (event.key === 'Enter' && newTeamName.trim()) {\n createTeam.mutate({ name: newTeamName.trim() });\n setNewTeamName('');\n setShowNewTeam(false);\n }\n if (event.key === 'Escape') {\n setShowNewTeam(false);\n setNewTeamName('');\n }\n }}\n />\n <button\n type=\"button\"\n onClick={() => {\n if (!newTeamName.trim()) {\n return;\n }\n createTeam.mutate({ name: newTeamName.trim() });\n setNewTeamName('');\n setShowNewTeam(false);\n }}\n disabled={!newTeamName.trim()}\n className=\"px-3 py-2 text-sm font-medium rounded-lg bg-imp-primary text-imp-primary-foreground hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n Create\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setShowNewTeam(false);\n setNewTeamName('');\n }}\n className=\"px-3 py-2 text-sm rounded-lg text-imp-muted-foreground hover:text-imp-foreground\"\n >\n Cancel\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => setShowNewTeam(true)}\n className=\"flex items-center gap-1.5 rounded-lg border border-imp-border px-3 py-2 text-sm font-medium text-imp-muted-foreground hover:border-imp-primary/50 hover:text-imp-foreground\"\n >\n <Plus className=\"w-4 h-4\" /> New Team\n </button>\n )\n ) : null}\n </div>\n\n {/* Two-pane layout */}\n <div\n className=\"grid h-[calc(100vh-220px)] min-h-130 border rounded-lg overflow-hidden\"\n style={{ gridTemplateColumns: '320px 1fr' }}\n >\n {/* Left: hierarchy tree */}\n <div className=\"flex flex-col overflow-hidden bg-imp-muted/20\">\n <div\n className=\"flex-1 px-1 py-2 overflow-y-auto\"\n onDragOver={(event) => {\n if (!draggedItem) {\n return;\n }\n // Root-level drop zone: only activate when not over a child scope row\n if (dropTarget === null) {\n event.preventDefault();\n setDropTarget('root');\n }\n }}\n onDragLeave={(event) => {\n const related = event.relatedTarget as Node | null;\n if (related && event.currentTarget.contains(related)) {\n return;\n }\n if (dropTarget === 'root') {\n setDropTarget(null);\n }\n }}\n onDrop={(event) => {\n event.preventDefault();\n if (!draggedItem) {\n return;\n }\n handleTriggerMove(draggedItem, null);\n }}\n >\n <div\n className={clsx(\n 'min-h-full rounded-lg py-1 transition-colors',\n dropTarget === 'root'\n ? 'bg-imp-primary/5 ring-1 ring-imp-primary/20 ring-inset'\n : '',\n )}\n >\n {isLoading ? (\n <div className=\"flex items-center justify-center px-4 py-12 text-sm text-center text-imp-muted-foreground\">\n Loading hierarchy…\n </div>\n ) : !hasTreeItems ? (\n <div className=\"flex flex-col items-center justify-center px-6 py-16 text-center\">\n <FolderInput className=\"w-10 h-10 mb-3 opacity-30 text-imp-muted-foreground\" />\n <h3 className=\"text-base font-medium text-imp-foreground\">\n {normalizedSearch ? 'No matching teams or flows' : 'No teams or flows yet'}\n </h3>\n <p className=\"max-w-sm mt-2 text-sm text-imp-muted-foreground\">\n {normalizedSearch\n ? 'Adjust the search to find a team or flow in the hierarchy.'\n : 'Create a team to start organizing flows and access scopes.'}\n </p>\n </div>\n ) : (\n <div className=\"space-y-1\">\n {filteredUnscopedFlows.map((flow) => (\n <FlowTreeRow\n key={flow.id}\n flow={flow}\n isSelected={selected?.kind === 'flow' && selected.id === flow.id}\n onSelect={(nextFlow) =>\n setSelected({ kind: 'flow', id: nextFlow.id, name: nextFlow.name })\n }\n />\n ))}\n\n {filteredScopes.map((scope) => (\n <ScopeTreeRow\n key={scope.id}\n scope={scope}\n allScopes={scopes}\n depth={0}\n onSelectScope={(nextScope) =>\n setSelected({ kind: 'team', id: nextScope.id, name: nextScope.name })\n }\n onSelectFlow={(nextFlow) =>\n setSelected({ kind: 'flow', id: nextFlow.id, name: nextFlow.name })\n }\n onTriggerMove={handleTriggerMove}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Right: detail panel */}\n <aside className=\"flex flex-col overflow-hidden border-l border-imp-border bg-imp-muted/30\">\n {!selected ? (\n <div className=\"flex flex-col items-center justify-center h-full gap-4 px-8 text-center text-imp-muted-foreground\">\n <div className=\"flex items-center justify-center w-12 h-12 rounded-xl bg-imp-primary/5\">\n <Shield className=\"w-6 h-6 text-imp-primary/40\" />\n </div>\n <div>\n <p className=\"text-sm font-medium text-imp-foreground\">Select a team or flow</p>\n <p className=\"mt-1.5 text-xs text-imp-muted-foreground max-w-[280px]\">\n Choose an item from the tree to manage its members and permissions.\n </p>\n </div>\n {hasTreeItems ? null : isAdmin ? (\n <button\n type=\"button\"\n onClick={() => setShowNewTeam(true)}\n className=\"flex items-center gap-1.5 rounded-lg border border-imp-border px-3 py-1.5 text-xs font-medium text-imp-foreground transition-colors hover:border-imp-primary/50 hover:bg-imp-muted/50\"\n >\n <Plus className=\"h-3.5 w-3.5\" /> Create your first team\n </button>\n ) : null}\n </div>\n ) : selected.kind === 'team' ? (\n <ScopeDetailPanel\n scopeId={selected.id}\n scopeName={selectedName ?? selected.name}\n users={users}\n userMap={userMap}\n teams={teams}\n isAdmin={!!isAdmin}\n />\n ) : (\n <FlowDetailPanel\n flowId={selected.id}\n flowName={selectedName ?? selected.name}\n users={users}\n userMap={userMap}\n teams={teams}\n isAdmin={!!isAdmin}\n />\n )}\n </aside>\n </div>\n\n {pendingMove ? (\n <MoveConfirmationDialog\n pendingMove={pendingMove}\n preview={movePreview}\n error={moveError}\n onClose={clearMove}\n />\n ) : null}\n </PageLayout>\n );\n}\n","/**\n * TeamsPage — Team management page with create/edit/delete teams and member management.\n */\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { ChevronDown, ChevronRight, Plus, Search, Trash2, User, Users, X } from 'lucide-react';\nimport { useApiClient, PageLayout } from '@invect/ui';\nimport { useRbac } from '../providers/RbacProvider';\nimport {\n useTeams,\n useTeam,\n useCreateTeam,\n useDeleteTeam,\n useAddTeamMember,\n useRemoveTeamMember,\n} from '../hooks/useTeams';\n\n// ─────────────────────────────────────────────────────────────\n// User fetching (reused from AccessControlPage pattern)\n// ─────────────────────────────────────────────────────────────\n\ninterface AuthUser {\n id: string;\n name?: string;\n email?: string;\n}\n\nfunction useUsers() {\n const api = useApiClient();\n const [users, setUsers] = useState<AuthUser[]>([]);\n\n useEffect(() => {\n let cancelled = false;\n fetch(`${api.getBaseURL()}/plugins/auth/users?limit=200`, { credentials: 'include' })\n .then((r) => (r.ok ? r.json() : null))\n .then((data) => {\n if (!cancelled && data?.users) {\n setUsers(data.users);\n }\n })\n .catch(() => {\n // intentionally ignored — UI will show empty state\n });\n return () => {\n cancelled = true;\n };\n }, [api]);\n\n return { users };\n}\n\n// ─────────────────────────────────────────────────────────────\n// Main Page\n// ─────────────────────────────────────────────────────────────\n\nexport function TeamsPage() {\n const { isAuthenticated, checkPermission } = useRbac();\n const teamsQuery = useTeams();\n const createTeam = useCreateTeam();\n const deleteTeam = useDeleteTeam();\n const { users } = useUsers();\n\n const [expandedTeamId, setExpandedTeamId] = useState<string | null>(null);\n const [teamSearch, setTeamSearch] = useState('');\n const [showCreateForm, setShowCreateForm] = useState(false);\n const [newTeamName, setNewTeamName] = useState('');\n const [newTeamDescription, setNewTeamDescription] = useState('');\n\n const teams = teamsQuery.data?.teams ?? [];\n const isAdmin = isAuthenticated && checkPermission('admin:*');\n\n const userMap = useMemo(() => {\n const map = new Map<string, AuthUser>();\n for (const u of users) {\n map.set(u.id, u);\n }\n return map;\n }, [users]);\n\n const filteredTeams = useMemo(() => {\n const q = teamSearch.trim().toLowerCase();\n if (!q) {\n return teams;\n }\n return teams.filter(\n (t) => t.name.toLowerCase().includes(q) || t.description?.toLowerCase().includes(q),\n );\n }, [teams, teamSearch]);\n\n const handleCreate = async () => {\n if (!newTeamName.trim()) {\n return;\n }\n await createTeam.mutateAsync({\n name: newTeamName.trim(),\n description: newTeamDescription.trim() || undefined,\n });\n setNewTeamName('');\n setNewTeamDescription('');\n setShowCreateForm(false);\n };\n\n const handleDelete = async (teamId: string) => {\n await deleteTeam.mutateAsync(teamId);\n if (expandedTeamId === teamId) {\n setExpandedTeamId(null);\n }\n };\n\n if (!isAuthenticated) {\n return (\n <div className=\"flex items-center justify-center w-full h-full min-h-0 overflow-y-auto imp-page bg-imp-background text-imp-foreground\">\n <p className=\"text-sm text-imp-muted-foreground\">Please sign in to access this page.</p>\n </div>\n );\n }\n\n return (\n <PageLayout\n title=\"Teams\"\n icon={Users}\n actions={\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-imp-muted-foreground\">\n {filteredTeams.length} team{filteredTeams.length !== 1 ? 's' : ''}\n </span>\n {isAdmin && (\n <button\n type=\"button\"\n onClick={() => setShowCreateForm(!showCreateForm)}\n className=\"flex items-center gap-1 px-2 py-1 text-xs font-medium rounded bg-imp-primary text-imp-primary-foreground hover:bg-imp-primary/90\"\n >\n <Plus className=\"w-3 h-3\" />\n New Team\n </button>\n )}\n </div>\n }\n >\n {/* Create team form */}\n {showCreateForm && (\n <div className=\"p-3 border rounded-lg border-imp-border bg-imp-card\">\n <div className=\"mb-2 text-xs font-medium text-imp-foreground\">Create Team</div>\n <div className=\"space-y-2\">\n <input\n type=\"text\"\n value={newTeamName}\n onChange={(e) => setNewTeamName(e.target.value)}\n placeholder=\"Team name\"\n className=\"w-full rounded border border-imp-border bg-imp-background px-2 py-1.5 text-sm placeholder:text-imp-muted-foreground\"\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n handleCreate();\n }\n }}\n />\n <input\n type=\"text\"\n value={newTeamDescription}\n onChange={(e) => setNewTeamDescription(e.target.value)}\n placeholder=\"Description (optional)\"\n className=\"w-full rounded border border-imp-border bg-imp-background px-2 py-1.5 text-sm placeholder:text-imp-muted-foreground\"\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n handleCreate();\n }\n }}\n />\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleCreate}\n disabled={createTeam.isPending || !newTeamName.trim()}\n className=\"px-3 py-1 text-xs font-medium rounded bg-imp-primary text-imp-primary-foreground hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n {createTeam.isPending ? 'Creating…' : 'Create'}\n </button>\n <button\n type=\"button\"\n onClick={() => setShowCreateForm(false)}\n className=\"px-3 py-1 text-xs rounded text-imp-muted-foreground hover:text-imp-foreground\"\n >\n Cancel\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Search */}\n <div className=\"relative\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-imp-muted-foreground\" />\n <input\n value={teamSearch}\n onChange={(e) => setTeamSearch(e.target.value)}\n placeholder=\"Search teams…\"\n className=\"w-full rounded-lg border border-imp-border bg-transparent py-2 pl-9 pr-3 text-sm outline-none placeholder:text-imp-muted-foreground focus:border-imp-primary/50\"\n />\n </div>\n\n {/* Teams list */}\n <div className=\"border rounded-lg border-imp-border bg-imp-card\">\n {teamsQuery.isLoading ? (\n <div className=\"px-4 py-8 text-sm text-center text-imp-muted-foreground\">Loading…</div>\n ) : teamsQuery.error ? (\n <div className=\"px-4 py-8 text-sm text-center text-red-500\">\n {teamsQuery.error instanceof Error ? teamsQuery.error.message : 'Failed to load teams'}\n </div>\n ) : filteredTeams.length === 0 ? (\n <div className=\"px-4 py-8 text-sm text-center text-imp-muted-foreground\">\n {teamSearch\n ? 'No teams match this search.'\n : 'No teams yet. Create one to get started.'}\n </div>\n ) : (\n <div className=\"divide-y divide-imp-border\">\n {filteredTeams.map((team) => {\n const isExpanded = expandedTeamId === team.id;\n return (\n <div key={team.id}>\n <div className=\"flex items-center gap-3 px-3 py-2\">\n <button\n type=\"button\"\n className=\"flex items-center flex-1 gap-3 text-left transition-opacity hover:opacity-80\"\n onClick={() => setExpandedTeamId(isExpanded ? null : team.id)}\n >\n {isExpanded ? (\n <ChevronDown className=\"h-3.5 w-3.5 shrink-0 text-imp-muted-foreground\" />\n ) : (\n <ChevronRight className=\"h-3.5 w-3.5 shrink-0 text-imp-muted-foreground\" />\n )}\n <Users className=\"h-3.5 w-3.5 shrink-0 text-imp-primary\" />\n <div className=\"flex-1 min-w-0\">\n <span className=\"block text-sm font-medium truncate\">{team.name}</span>\n {team.description && (\n <span className=\"block text-xs truncate text-imp-muted-foreground\">\n {team.description}\n </span>\n )}\n </div>\n </button>\n {isAdmin && (\n <button\n type=\"button\"\n onClick={() => handleDelete(team.id)}\n className=\"p-1 rounded shrink-0 text-imp-muted-foreground hover:text-red-500\"\n title=\"Delete team\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </div>\n {isExpanded && (\n <TeamMembersPanel\n teamId={team.id}\n users={users}\n userMap={userMap}\n isAdmin={!!isAdmin}\n />\n )}\n </div>\n );\n })}\n </div>\n )}\n </div>\n </PageLayout>\n );\n}\n\n// ─────────────────────────────────────────────────────────────\n// Team members panel (inline, shown when a team is expanded)\n// ─────────────────────────────────────────────────────────────\n\nfunction TeamMembersPanel({\n teamId,\n users,\n userMap,\n isAdmin,\n}: {\n teamId: string;\n users: AuthUser[];\n userMap: Map<string, AuthUser>;\n isAdmin: boolean;\n}) {\n const { data, isLoading } = useTeam(teamId);\n const addMember = useAddTeamMember(teamId);\n const removeMember = useRemoveTeamMember(teamId);\n\n const members = data?.members ?? [];\n const existingUserIds = new Set(members.map((m) => m.userId));\n\n const getUserLabel = (userId: string) => {\n const u = userMap.get(userId);\n return u?.name || u?.email || userId;\n };\n\n const [selectedUserId, setSelectedUserId] = useState<string | null>(null);\n\n const handleAdd = async () => {\n if (!selectedUserId) {\n return;\n }\n await addMember.mutateAsync({ userId: selectedUserId });\n setSelectedUserId(null);\n };\n\n const handleRemove = async (userId: string) => {\n await removeMember.mutateAsync(userId);\n };\n\n return (\n <div className=\"px-3 pt-2 pb-3 border-t border-imp-border bg-imp-muted/20\">\n {isLoading ? (\n <p className=\"py-3 text-xs text-center text-imp-muted-foreground\">Loading…</p>\n ) : members.length === 0 ? (\n <p className=\"py-2 text-xs text-imp-muted-foreground\">No members yet.</p>\n ) : (\n <div className=\"mb-2 space-y-1\">\n {members.map((member) => (\n <div key={member.id} className=\"flex items-center gap-2 px-2 py-1 text-xs rounded\">\n <div className=\"flex items-center justify-center w-5 h-5 rounded-full shrink-0 bg-imp-primary/10\">\n <User className=\"w-3 h-3 text-imp-primary\" />\n </div>\n <span className=\"flex-1 min-w-0 truncate\">{getUserLabel(member.userId)}</span>\n {isAdmin && (\n <button\n type=\"button\"\n onClick={() => handleRemove(member.userId)}\n className=\"shrink-0 rounded p-0.5 text-imp-muted-foreground hover:text-red-500\"\n title=\"Remove member\"\n >\n <Trash2 className=\"w-3 h-3\" />\n </button>\n )}\n </div>\n ))}\n </div>\n )}\n\n {isAdmin && (\n <div className=\"flex items-center gap-1.5\">\n <MemberSearchCombobox\n users={users}\n excludeIds={existingUserIds}\n selectedUserId={selectedUserId}\n onSelect={setSelectedUserId}\n />\n <button\n type=\"button\"\n onClick={handleAdd}\n disabled={addMember.isPending || !selectedUserId}\n className=\"shrink-0 rounded bg-imp-primary px-2.5 py-1 text-xs font-medium text-imp-primary-foreground hover:bg-imp-primary/90 disabled:opacity-50\"\n >\n {addMember.isPending ? '…' : 'Add'}\n </button>\n </div>\n )}\n </div>\n );\n}\n\n// ─────────────────────────────────────────────────────────────\n// Member search combobox\n// ─────────────────────────────────────────────────────────────\n\nfunction MemberSearchCombobox({\n users,\n excludeIds,\n selectedUserId,\n onSelect,\n}: {\n users: AuthUser[];\n excludeIds: Set<string>;\n selectedUserId: string | null;\n onSelect: (userId: string | null) => void;\n}) {\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState('');\n const containerRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n const selectedUser = selectedUserId ? users.find((u) => u.id === selectedUserId) : null;\n\n const filtered = useMemo(() => {\n const q = query.toLowerCase();\n return users.filter((u) => {\n if (excludeIds.has(u.id)) {\n return false;\n }\n if (!q) {\n return true;\n }\n return (\n u.name?.toLowerCase().includes(q) ||\n u.email?.toLowerCase().includes(q) ||\n u.id.toLowerCase().includes(q)\n );\n });\n }, [users, excludeIds, query]);\n\n useEffect(() => {\n const handleClick = (e: MouseEvent) => {\n if (containerRef.current && !containerRef.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n if (open) {\n document.addEventListener('mousedown', handleClick);\n return () => document.removeEventListener('mousedown', handleClick);\n }\n }, [open]);\n\n return (\n <div ref={containerRef} className=\"relative flex-1 min-w-0\">\n {selectedUser ? (\n <button\n type=\"button\"\n onClick={() => {\n onSelect(null);\n setQuery('');\n }}\n className=\"flex w-full items-center gap-1.5 rounded border border-imp-border bg-imp-background px-2 py-1 text-xs text-left\"\n >\n <User className=\"w-3 h-3 shrink-0 text-imp-muted-foreground\" />\n <span className=\"flex-1 min-w-0 truncate\">\n {selectedUser.name || selectedUser.email || selectedUser.id}\n </span>\n <X className=\"w-3 h-3 shrink-0 text-imp-muted-foreground\" />\n </button>\n ) : (\n <div className=\"relative\">\n <Search className=\"absolute w-3 h-3 -translate-y-1/2 pointer-events-none left-2 top-1/2 text-imp-muted-foreground\" />\n <input\n ref={inputRef}\n type=\"text\"\n value={query}\n onChange={(e) => {\n setQuery(e.target.value);\n if (!open) {\n setOpen(true);\n }\n }}\n onFocus={() => setOpen(true)}\n placeholder=\"Search users…\"\n className=\"w-full py-1 pl-6 pr-2 text-xs border rounded border-imp-border bg-imp-background placeholder:text-imp-muted-foreground\"\n />\n </div>\n )}\n\n {open && !selectedUser && (\n <div className=\"absolute left-0 z-50 w-full mt-1 border rounded-md shadow-lg top-full border-imp-border bg-imp-background\">\n <div className=\"py-1 overflow-y-auto max-h-40\">\n {filtered.length === 0 ? (\n <p className=\"px-3 py-2 text-xs text-imp-muted-foreground\">No users found.</p>\n ) : (\n filtered.map((u) => (\n <button\n key={u.id}\n type=\"button\"\n onClick={() => {\n onSelect(u.id);\n setQuery('');\n setOpen(false);\n }}\n className=\"flex w-full items-center gap-2 px-2 py-1.5 text-left text-xs hover:bg-imp-muted/50 transition-colors\"\n >\n <User className=\"h-3.5 w-3.5 shrink-0 text-imp-muted-foreground\" />\n <span className=\"flex-1 min-w-0 truncate\">{u.name || u.email || u.id}</span>\n </button>\n ))\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n","/**\n * UserMenuSection — Sidebar footer component showing current user info.\n *\n * Displays the authenticated user's name and role in the sidebar footer area.\n * This is a standalone component — not directly injected via plugin system\n * but available for host apps to use in custom sidebar layouts.\n */\n\nimport { useRbac } from '../providers/RbacProvider';\n\nexport function UserMenuSection({ collapsed = false }: { collapsed?: boolean }) {\n const { user, isAuthenticated, isLoading } = useRbac();\n\n if (isLoading || !isAuthenticated || !user) {\n return null;\n }\n\n const initials = (user.name ?? user.id)[0]?.toUpperCase() ?? '?';\n\n if (collapsed) {\n return (\n <div\n className=\"flex justify-center px-2 py-2\"\n title={`${user.name ?? user.id} (${user.role ?? 'user'})`}\n >\n <div className=\"flex h-8 w-8 items-center justify-center rounded-full bg-imp-primary/10 text-xs font-medium text-imp-primary\">\n {initials}\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"flex items-center gap-3 px-3 py-2\">\n <div className=\"flex h-8 w-8 items-center justify-center rounded-full bg-imp-primary/10 text-xs font-medium text-imp-primary\">\n {initials}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium\">{user.name ?? user.id}</p>\n <p className=\"truncate text-xs text-imp-muted-foreground capitalize\">\n {user.role ?? 'user'}\n </p>\n </div>\n </div>\n );\n}\n\nexport function UserAvatar({ className }: { className?: string }) {\n const { user, isAuthenticated } = useRbac();\n\n if (!isAuthenticated || !user) {\n return null;\n }\n\n const initials = (user.name ?? user.id)[0]?.toUpperCase() ?? '?';\n\n return (\n <div\n className={`flex items-center justify-center rounded-full bg-imp-primary/10 text-xs font-medium text-imp-primary ${className ?? 'h-6 w-6'}`}\n title={user.name ?? user.id}\n >\n {initials}\n </div>\n );\n}\n","/**\n * @invect/rbac/ui — Frontend Plugin Entry Point\n *\n * This is the browser-safe entry point that exports the RBAC frontend plugin.\n * Import via: `import { rbacFrontend } from '@invect/rbac/ui'`\n *\n * No Node.js dependencies. No @invect/core runtime imports.\n */\n\nimport { Shield } from 'lucide-react';\nimport { RbacProvider, useRbac } from './providers/RbacProvider';\nimport { ShareButton } from './components/ShareButton';\nimport { FlowAccessPanel } from './components/FlowAccessPanel';\nimport { AccessControlPage } from './components/AccessControlPage';\nimport type { InvectFrontendPlugin } from './types';\n\n// ─────────────────────────────────────────────────────────────\n// RBAC Frontend Plugin Definition\n// ─────────────────────────────────────────────────────────────\n\nexport const rbacFrontend: InvectFrontendPlugin = {\n id: 'rbac',\n name: 'Role-Based Access Control',\n\n // ─── Providers ───\n // Wraps the app tree with RBAC context (current user, permissions cache)\n providers: [RbacProvider],\n\n // ─── Sidebar ───\n sidebar: [\n {\n label: 'Access Control',\n icon: Shield,\n path: '/access',\n position: 'top',\n permission: 'flow:read',\n },\n ],\n\n // ─── Routes ───\n routes: [\n {\n path: '/access',\n component: AccessControlPage,\n },\n ],\n\n // ─── Panel Tabs ───\n panelTabs: [\n {\n context: 'flowEditor',\n label: 'Access',\n icon: Shield,\n component: FlowAccessPanel,\n permission: 'flow:read',\n },\n ],\n\n // ─── Header Actions ───\n headerActions: [\n {\n context: 'flowHeader',\n component: ShareButton,\n permission: 'flow:read',\n },\n ],\n\n // ─── Component Implementations ───\n // These resolve backend-declared componentIds to actual React components\n components: {\n 'rbac.AccessControlPage': AccessControlPage as unknown as React.ComponentType<\n Record<string, unknown>\n >,\n 'rbac.FlowAccessPanel': FlowAccessPanel as unknown as React.ComponentType<\n Record<string, unknown>\n >,\n 'rbac.ShareButton': ShareButton as unknown as React.ComponentType<Record<string, unknown>>,\n },\n\n // ─── Permission Checking ───\n // Delegates to the RbacProvider's cached permissions.\n // This is called by the host app's plugin registry to gate UI elements.\n checkPermission: (_permission: string, _context?) => {\n // We can't call useRbac() here (not in a React component).\n // Return undefined to defer to the registry's default behavior.\n // The actual permission check happens via useRbac().checkPermission()\n // inside each component that needs it.\n return undefined;\n },\n};\n\n// ─────────────────────────────────────────────────────────────\n// Re-exports for direct use\n// ─────────────────────────────────────────────────────────────\n\n// Provider & hook\nexport { RbacProvider, useRbac };\n\n// Components (for custom layouts)\nexport { ShareButton } from './components/ShareButton';\nexport { ShareFlowModal } from './components/ShareFlowModal';\nexport { FlowAccessPanel } from './components/FlowAccessPanel';\nexport { AccessControlPage } from './components/AccessControlPage';\nexport { TeamsPage } from './components/TeamsPage';\nexport { UserMenuSection, UserAvatar } from './components/UserMenuSection';\n\n// Hooks\nexport {\n useAccessibleFlows,\n useFlowAccess,\n useGrantFlowAccess,\n useRevokeFlowAccess,\n} from './hooks/useFlowAccess';\n\nexport {\n useTeams,\n useTeam,\n useMyTeams,\n useUpdateTeam,\n useCreateTeam,\n useDeleteTeam,\n useAddTeamMember,\n useRemoveTeamMember,\n} from './hooks/useTeams';\n\nexport {\n useScopeTree,\n useScopeAccess,\n useGrantScopeAccess,\n useRevokeScopeAccess,\n useEffectiveFlowAccess,\n useMoveFlow,\n usePreviewMove,\n} from './hooks/useScopes';\n\n// Types\nexport type {\n InvectFrontendPlugin,\n PluginSidebarContribution,\n PluginRouteContribution,\n PluginPanelTabContribution,\n PluginHeaderActionContribution,\n PanelTabProps,\n HeaderActionProps,\n PermissionContext,\n} from './types';\n"],"mappings":"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"}