# Unified Access Management Hub

## TL;DR

> **Quick Summary**: Merge `/dashboard/keys`, `/dashboard/users`, and `/dashboard/packages` into a single tabbed "Access Management" hub at `/dashboard/access`. Eliminate duplicate API key displays, streamline AddUserModal, and simplify user detail page.
>
> **Deliverables**:
> - New `/dashboard/access` page with 3 tabs (Users, API Keys, Packages)
> - Expandable user rows with inline key/limits summary
> - Simplified AddUserModal (username + password + role only)
> - Simplified user detail page (2 cards instead of 4)
> - Updated sidebar navigation with single "Access" entry
> - Backwards-compatible redirects from old routes
>
> **Estimated Effort**: Medium
> **Parallel Execution**: YES - 3 waves
> **Critical Path**: Task 1 (Hub Shell) → Task 2-4 (Tab Content) → Task 5-7 (Simplify & Polish) → F1-F4

---

## Context

### Original Request
User asked to analyze `/dashboard/keys` and `/dashboard/users`, identify duplication, and create a unified management solution that is "paling recommend dan efisien dan paling powerful."

### Interview Summary
**Key Discussions**:
- API Keys displayed in 2 places: keys page (full CRUD) and user detail page (read-only + generate)
- RTK/Caveman settings in 3 places: keys page inline, AddUserModal, and create-with-key API
- User→Key navigation via 2 different paths: keys page filter dropdown OR user detail page
- Recommendation: "Access Management Hub" with tabbed layout + inline expansion

**Research Findings**:
- `Sidebar.js` lines 24-33: Keys in "AI Config", Users+Packages in "User Management"
- `keys/page.js` (517 lines): Full client-side keys management with inline RTK/Caveman
- `UsersClient.jsx` (188 lines): User list with approve/delete/edit
- `AddUserModal.jsx` (345 lines): 5-section modal (username, password, package, RTK, Caveman)
- `users/[id]/page.js` (738 lines): 4 cards (Identity, Limits, Package, API Keys)
- `PackagesClient.jsx` (510 lines): Full packages CRUD
- All API routes support the required queries
- Non-admin sidebar: only Endpoint + Usage + Billing + Profile

### Metis Review
**Identified Gaps** (addressed):
- Packages tab scope: embed full PackagesClient as 3rd tab
- RTK/Caveman location: remove from AddUserModal, keep per-key only
- User detail page: keep but simplify to 2 cards, remove inline keys list
- Non-admin access: only API Keys tab visible
- Backwards compatibility: redirect old routes to hub
- Tab state: URL search params for deep-linking

---

## Work Objectives

### Core Objective
Consolidate three separate admin pages (Keys, Users, Packages) into a single tabbed Access Management Hub to eliminate navigation overhead and duplicate data displays.

### Concrete Deliverables
- `src/app/(dashboard)/dashboard/access/page.js` — Hub page (Server Component)
- `src/app/(dashboard)/dashboard/access/AccessHubClient.jsx` — Main client component
- `src/app/(dashboard)/dashboard/access/tabs/UsersTab.jsx` — Users list
- `src/app/(dashboard)/dashboard/access/tabs/KeysTab.jsx` — API Keys list
- `src/app/(dashboard)/dashboard/access/tabs/PackagesTab.jsx` — Packages CRUD
- `src/app/(dashboard)/dashboard/access/components/UserExpandableRow.jsx` — Inline expansion
- Modified: `Sidebar.js` — Single "Access" entry
- Modified: `users/[id]/page.js` — Simplified to 2 cards
- Modified: `AddUserModal.jsx` — RTK/Caveman removed
- Modified: old pages → redirects

### Must Have
- Tabbed hub with URL-based tab state (`?tab=users|keys|packages`)
- Expandable user rows showing key summary + limits summary
- Inline RTK/Caveman editing on API Keys tab
- User detail page simplified (no duplicate keys list)
- Backwards-compatible redirects from old routes
- Non-admin view (API Keys tab only)

### Must NOT Have
- NO API route changes
- NO database schema changes
- NO new npm dependencies
- NO changes to non-admin sidebar
- NO removal of user detail page
- NO over-abstraction
- NO AI slop

---

## Verification Strategy

### Test Decision
- Infrastructure exists: YES (vitest)
- Automated tests: None (no UI tests in project)

### QA Policy
Every task MUST include agent-executed QA scenarios with Playwright.

---

## Execution Strategy

### Parallel Execution Waves

```
Wave 1 (foundation):
├── Task 1: Hub shell + tab routing [quick]
├── Task 2: UsersTab [visual-engineering]
└── Task 3: KeysTab [visual-engineering]

Wave 2 (expansion):
├── Task 4: PackagesTab [visual-engineering]
├── Task 5: UserExpandableRow [visual-engineering]
└── Task 6: Sidebar + redirects [quick]

Wave 3 (simplify):
├── Task 7: Simplify AddUserModal [quick]
├── Task 8: Simplify user detail [quick]
└── Task 9: Non-admin + edge cases [unspecified-high]

Wave FINAL:
├── F1: Plan compliance (oracle)
├── F2: Code quality (unspecified-high)
├── F3: Manual QA (unspecified-high + playwright)
└── F4: Scope fidelity (deep)
```

### Dependency Matrix

| Task | Depends On | Blocks |
|------|-----------|--------|
| 1 | - | 2, 3, 4, 5, 6, 7, 8, 9 |
| 2 | 1 | 5, 7, 8, 9 |
| 3 | 1 | 5, 7, 8, 9 |
| 4 | 1 | 6, 9 |
| 5 | 1, 2, 3 | 7, 8, 9 |
| 6 | 1, 4 | 9 |
| 7 | 2, 5 | 9 |
| 8 | 2, 5 | 9 |
| 9 | all above | F1-F4 |

### Agent Dispatch Summary

| Wave | Tasks | Categories |
|------|-------|-----------|
| 1 | 3 | quick, visual-engineering, visual-engineering |
| 2 | 3 | visual-engineering, visual-engineering, quick |
| 3 | 3 | quick, quick, unspecified-high |
| FINAL | 4 | oracle, unspecified-high, unspecified-high+playwright, deep |

---

## TODOs

For each task below, include: What to do, Must NOT do, Recommended Agent Profile, Parallelization, References (Pattern/API/Component), Acceptance Criteria with QA Scenarios (happy path + error case), and Commit info.

### 1. Hub Page Shell + Tab Routing ✅
- Create Server Component wrapper at `access/page.js` (auth check via cookies + verifyToken)
- Create client component `AccessHubClient.jsx` with 3-tab layout
- Tab state via `useSearchParams` (?tab=users|keys|packages)
- Default tab: users for admin, keys for non-admin
- Horizontal tab bar with Material Symbols icons
- Each tab renders placeholder div initially
- Fetch current user via /api/auth/me for admin check
- Category: quick | Wave 1 | Blocks: 2-9

**Acceptance Criteria**:

**QA Scenarios:**

Scenario: Admin navigates to hub and sees 3 tabs
  Tool: Playwright
  Steps: Login as admin, go to /dashboard/access, verify Users, API Keys, Packages tabs visible
  Expected Result: 3 tabs visible with correct labels and icons
  Evidence: .omo/evidence/task-1-scenario.png

Scenario: Tab navigation updates URL and content
  Tool: Playwright
  Steps: Click "API Keys" tab, verify URL contains ?tab=keys, click "Packages" tab, verify URL contains ?tab=packages
  Expected Result: URL updates correctly, tab content changes
  Evidence: .omo/evidence/task-1-scenario-url.png

### 2. UsersTab - Migrate from UsersClient.jsx ✅
- Create `tabs/UsersTab.jsx`
- Migrate user list logic from UsersClient.jsx (approve, delete, row rendering)
- Data table layout: User, Role, Status, Keys count, Package, RPM, Actions
- Fetch users via /api/users, fetch keys via /api/keys?all=true, group by userId
- Include AddUserModal import, search input
- Category: visual-engineering | Wave 1 | Depends: 1

**Acceptance Criteria**:

**QA Scenarios:**

Scenario: Users tab shows table with correct columns
  Tool: Playwright
  Steps: Navigate to /dashboard/access?tab=users, verify table header has User, Role, Status, Keys count, Package, RPM, Actions columns
  Expected Result: All columns visible with proper data
  Evidence: .omo/evidence/task-2-scenario.png

Scenario: Approve/delete actions work correctly
  Tool: Playwright
  Steps: Click approve on pending user, verify status changes to Approved; click delete, confirm modal, verify user removed
  Expected Result: User status changes, user removed from list
  Evidence: .omo/evidence/task-2-scenario-actions.png

### 3. KeysTab - Migrate from keys/page.js ✅
- Create `tabs/KeysTab.jsx`
- Migrate key management from keys/page.js (create, toggle, delete, copy, RTK/Caveman)
- Add owner column (fetch users, map userId to username)
- Add search/filter by name, filter by user dropdown
- Inline RTK/Caveman editing via PATCH endpoint
- Category: visual-engineering | Wave 1 | Depends: 1

**Acceptance Criteria**:

**QA Scenarios:**

Scenario: Keys tab shows list with owner column
  Tool: Playwright
  Steps: Navigate to /dashboard/access?tab=keys, verify keys visible with owner column populated
  Expected Result: Keys list displays, owner column shows usernames
  Evidence: .omo/evidence/task-3-scenario.png

Scenario: Create key modal works
  Tool: Playwright
  Steps: Click create key, fill form with name, submit, verify key appears in list
  Expected Result: New key appears in table with correct name
  Evidence: .omo/evidence/task-3-scenario-create.png

### 4. PackagesTab - Embed PackagesClient ✅
- Create `tabs/PackagesTab.jsx`
- Import and render PackagesClient component with data fetching
- Adapt to work as tab (fetch packages on mount, not SSR)
- Category: visual-engineering | Wave 2 | Depends: 1

**Acceptance Criteria**:

**QA Scenarios:**

Scenario: Packages tab renders package list
  Tool: Playwright
  Steps: Navigate to /dashboard/access?tab=packages, verify package list visible with name, price, limits
  Expected Result: Package data loads and displays correctly
  Evidence: .omo/evidence/task-4-scenario.png

Scenario: Add/edit/delete package works
  Tool: Playwright
  Steps: Click add package, fill form, submit; edit existing package; delete package
  Expected Result: Package operations succeed, list updates accordingly
  Evidence: .omo/evidence/task-4-scenario-crud.png

### 5. UserExpandableRow Component ✅
- Create `components/UserExpandableRow.jsx`
- Click row to expand, shows: API keys list (name, status, RTK, Caveman), limits summary, package info
- Lazy-load data on expand (fetch keys/limits/package for that user)
- Quick actions: toggle key, generate key, edit limits
- Category: visual-engineering | Wave 2 | Depends: 1, 2, 3

**Acceptance Criteria**:

**QA Scenarios:**

Scenario: User row expands on click
  Tool: Playwright
  Steps: Click user row in Users tab, verify expansion panel visible with keys and limits
  Expected Result: Expansion panel shows, API calls made on expand
  Evidence: .omo/evidence/task-5-scenario.png

Scenario: Collapse works correctly
  Tool: Playwright
  Steps: Click expanded row again, verify panel collapses
  Expected Result: Panel collapses, no errors
  Evidence: .omo/evidence/task-5-scenario-collapse.png

### 6. Sidebar Update + Route Redirects ✅
- Modify Sidebar.js: remove Keys from aiConfigItems, replace Users+Packages in userManagementItems with single "Access" entry
- Add redirects: keys/page.js → /dashboard/access?tab=keys, users/page.js → /dashboard/access?tab=users, packages/page.js → /dashboard/access?tab=packages
- Non-admin: add "My API Keys" entry pointing to /dashboard/access?tab=keys
- Category: quick | Wave 2 | Depends: 1, 4

**Acceptance Criteria**:

**QA Scenarios:**

Scenario: Sidebar shows single Access entry
  Tool: Playwright
  Steps: Inspect sidebar DOM, verify single "Access" entry present
  Expected Result: One Access entry visible in sidebar
  Evidence: .omo/evidence/task-6-scenario.png

Scenario: Old routes redirect to hub
  Tool: Playwright
  Steps: Navigate to /dashboard/keys, verify redirect to /dashboard/access?tab=keys; navigate to /dashboard/users, verify redirect to /dashboard/access?tab=users
  Expected Result: Redirects work correctly, URL updates
  Evidence: .omo/evidence/task-6-scenario-redirect.png

### 7. Simplify AddUserModal ✅
- Remove RTK toggle, Caveman toggle, Caveman level from AddUserModal.jsx
- Keep only: username, password (with auto-generate), role select
- Update /api/users/create-with-key call to not pass rtkEnabled/cavemanEnabled
- Category: quick | Wave 3 | Depends: 2, 5

**Acceptance Criteria**:

**QA Scenarios:**

Scenario: AddUserModal shows only username, password, role
  Tool: Playwright
  Steps: Open AddUserModal in Users tab, verify only username, password, role fields visible
  Expected Result: No RTK/Caveman fields present
  Evidence: .omo/evidence/task-7-scenario.png

Scenario: Create user works with simplified modal
  Tool: Playwright
  Steps: Fill username, password, select role, submit form
  Expected Result: User created successfully, appears in users list
  Evidence: .omo/evidence/task-7-scenario-create.png

### 8. Simplify User Detail Page ✅
- Remove API Keys card from users/[id]/page.js
- Add link "View API Keys (N)" that navigates to /dashboard/access?tab=keys with user filter
- Merge "Custom Rate Limits" + "Subscription Package" into single "Access & Limits" card
- Category: quick | Wave 3 | Depends: 2, 5

**Acceptance Criteria**:

**QA Scenarios:**

Scenario: User detail page has 2 cards
  Tool: Playwright
  Steps: Navigate to user detail page, verify Identity card and Access & Limits card visible
  Expected Result: 2 cards present, no API Keys card
  Evidence: .omo/evidence/task-8-scenario.png

Scenario: "View API Keys" link works
  Tool: Playwright
  Steps: Click "View API Keys" link, verify navigation to keys tab filtered by user
  Expected Result: Navigation to /dashboard/access?tab=keys with user filter applied
  Evidence: .omo/evidence/task-8-scenario-link.png

### 9. Non-admin View + Edge Cases ✅
- Handle non-admin access: only show API Keys tab
- Handle empty states for all tabs
- Handle tab switching with data refresh
- Handle direct URL access to old routes (redirect)
- Error boundary for each tab
- Category: unspecified-high | Wave 3 | Depends: all above

**Acceptance Criteria**:

**QA Scenarios:**

Scenario: Non-admin sees only API Keys tab
  Tool: Playwright
  Steps: Login as non-admin, navigate to /dashboard/access, verify only API Keys tab visible
  Expected Result: Only one tab visible, Users and Packages tabs hidden
  Evidence: .omo/evidence/task-9-scenario.png

Scenario: Tab switching refreshes data
  Tool: Playwright
  Steps: Click between tabs, verify data refreshes for each tab
  Expected Result: Each tab loads fresh data when selected
  Evidence: .omo/evidence/task-9-scenario-refresh.png

---

## Final Verification Wave

- [x] F1. Plan Compliance Audit — `oracle`
  Read plan end-to-end. For each Must Have: verify implementation exists. For each Must NOT Have: search for forbidden patterns. Check evidence files.
  Output: Must Have [N/N] | Must NOT Have [N/N] | VERDICT

- [x] F2. Code Quality Review — `unspecified-high`
  Run npm run build. Review all changed files for AI slop, unused imports, console.log, commented-out code.
  Output: Build [PASS/FAIL] | Files [N clean/N issues] | VERDICT

- [x] F3. Real Manual QA — `unspecified-high` + `playwright`
  Test all CRUD operations from hub. Test redirects. Test non-admin view. Capture screenshots.
  Output: Scenarios [N/N pass] | VERDICT

- [x] F4. Scope Fidelity Check — `deep`
  Verify each task matches spec. Check no API routes were modified. Check no DB changes.
  Output: Tasks [N/N compliant] | VERDICT

---

## Commit Strategy

| After | Message | Files |
|-------|---------|-------|
| 1 | feat(access): hub page shell with tab routing | access/page.js, AccessHubClient.jsx |
| 2-3 | feat(access): migrate users and keys tab content | tabs/UsersTab.jsx, tabs/KeysTab.jsx |
| 4-5 | feat(access): packages tab and expandable user rows | tabs/PackagesTab.jsx, UserExpandableRow.jsx |
| 6 | refactor(sidebar): unified access entry + route redirects | Sidebar.js, old pages |
| 7-8 | refactor(access): simplify AddUserModal and user detail | AddUserModal.jsx, users/[id]/page.js |
| 9 | fix(access): non-admin view and edge cases | Various |

---

## Success Criteria

### Verification Commands
```bash
npm run build          # Expected: Build successful
npx vitest run         # Expected: All tests pass
```

### Final Checklist
- [ ] Hub at /dashboard/access with 3 tabs for admin
- [ ] Non-admin sees only API Keys tab
- [ ] Old routes redirect to hub
- [ ] Sidebar shows single "Access" entry
- [ ] Key CRUD works from hub
- [ ] User CRUD works from hub
- [ ] Expandable rows work
- [ ] Packages CRUD works from tab
- [ ] User detail has 2 cards
- [ ] AddUserModal has 3 fields
- [ ] npm run build passes
- [ ] No API routes modified
