--- phase: 05-employee-design plan: 04 type: execute wave: 1 depends_on: [] files_modified: - packages/portal/proxy.ts - packages/portal/app/(dashboard)/agents/page.tsx - packages/portal/components/wizard-steps/step-review.tsx autonomous: true gap_closure: true requirements: [EMPL-04] must_haves: truths: - "customer_operator is redirected away from /agents/new (and all sub-paths) by proxy.ts before reaching creation UI" - "customer_operator does not see the New Employee button on the agents list page" - "Wizard deploy failure displays a visible error message to the user" artifacts: - path: "packages/portal/proxy.ts" provides: "RBAC redirect for /agents/new paths" contains: "/agents/new" - path: "packages/portal/app/(dashboard)/agents/page.tsx" provides: "Role-gated New Employee button" contains: "useSession" - path: "packages/portal/components/wizard-steps/step-review.tsx" provides: "Visible error handling on deploy failure" key_links: - from: "packages/portal/proxy.ts" to: "CUSTOMER_OPERATOR_RESTRICTED" via: "/agents/new added to restricted array" pattern: '"/agents/new"' - from: "packages/portal/components/wizard-steps/step-review.tsx" to: "error UI div" via: "re-thrown error sets createAgent.isError" pattern: "throw" --- Close two verification gaps from Phase 5 Employee Design: 1. Frontend RBAC gap: customer_operator can navigate to /agents/new and sub-paths (proxy.ts missing restriction) and sees the New Employee button (no role guard) 2. Wizard deploy error handling: catch block swallows errors so the error UI never renders Purpose: Complete EMPL-04 compliance (RBAC-enforced access) and fix silent deploy failure UX Output: Three patched files — proxy.ts, agents/page.tsx, step-review.tsx @/home/adelorenzo/.claude/get-shit-done/workflows/execute-plan.md @/home/adelorenzo/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/05-employee-design/05-VERIFICATION.md From packages/portal/proxy.ts (line 23): ```typescript const CUSTOMER_OPERATOR_RESTRICTED = ["/billing", "/settings/api-keys", "/users", "/admin"]; ``` From packages/portal/app/(dashboard)/agents/page.tsx (line 74): ```typescript ``` From packages/portal/components/wizard-steps/step-review.tsx (lines 28-53): ```typescript const handleDeploy = async () => { try { const agent = await createAgent.mutateAsync({ tenantId, data: { /* ... */ }, }); router.push(`/agents/${agent.id}?tenant=${tenantId}`); } catch (err) { console.error("Failed to deploy agent:", err); } }; ``` Error display div (lines 141-145): ```typescript {createAgent.error && (

{createAgent.error.message}

)} ``` Session pattern used in portal: ```typescript import { useSession } from "next-auth/react"; const { data: session } = useSession(); const role = (session?.user as { role?: string })?.role; ```
Task 1: Add /agents/new to proxy RBAC restrictions and hide New Employee button for operators packages/portal/proxy.ts, packages/portal/app/(dashboard)/agents/page.tsx 1. In proxy.ts, add "/agents/new" to the CUSTOMER_OPERATOR_RESTRICTED array (line 23). The existing startsWith check on line 59 already handles sub-paths, so adding "/agents/new" will automatically block /agents/new/templates, /agents/new/wizard, and /agents/new/advanced. 2. In agents/page.tsx, add role-based visibility to the New Employee button: - Import useSession from "next-auth/react" - Get session via useSession() hook - Extract role: `const role = (session?.user as { role?: string })?.role` - Wrap the New Employee Button in a conditional: only render when role is "platform_admin" or "customer_admin" (i.e., hide when role is "customer_operator" or undefined) - Use: `{role && role !== "customer_operator" && (