--- phase: 05-employee-design plan: "04" subsystem: portal tags: [rbac, ux, bugfix, gap-closure] dependency_graph: requires: [05-03] provides: [EMPL-04-complete] affects: [proxy.ts, agents-page, wizard-deploy] tech_stack: added: [] patterns: [useSession role gate, proxy RBAC restriction, TanStack Query error re-throw] key_files: created: [] modified: - packages/portal/proxy.ts - packages/portal/app/(dashboard)/agents/page.tsx - packages/portal/components/wizard-steps/step-review.tsx decisions: - "/agents/new added to CUSTOMER_OPERATOR_RESTRICTED — startsWith check already covers all sub-paths (wizard, templates, advanced)" - "Button hidden with role guard in addition to proxy redirect — security at proxy, UX polish at component" - "catch re-throw is minimal fix — existing createAgent.error UI was correctly wired, just never received the error" metrics: duration: "~1 min" completed: "2026-03-25" tasks: 2 files: 3 requirements: [EMPL-04] --- # Phase 5 Plan 4: RBAC Gap Closure and Wizard Error Fix Summary **One-liner:** Closed two verification gaps — proxy RBAC blocks /agents/new for operators and wizard deploy errors now surface to user via TanStack Query mutation state. ## Tasks Completed | Task | Name | Commit | Files | |------|------|--------|-------| | 1 | Add /agents/new to proxy RBAC restrictions and hide New Employee button | 8b697aa | proxy.ts, agents/page.tsx | | 2 | Fix wizard deploy error handling to surface errors to user | 67b3690 | step-review.tsx | ## What Was Built ### Task 1: Frontend RBAC Gap Closure Two changes to close the operator access gap for agent creation: **proxy.ts** — Added `"/agents/new"` to `CUSTOMER_OPERATOR_RESTRICTED` array. The existing `startsWith` check at line 59 automatically extends protection to all sub-paths (`/agents/new/templates`, `/agents/new/wizard`, `/agents/new/advanced`). No additional logic needed. **agents/page.tsx** — Added `useSession` import from `next-auth/react`, extracted `role` from session, and wrapped the New Employee button in a conditional render: `{role && role !== "customer_operator" && (