# Project Memory - Permissions Review

## Role-Based Access Rules

### 1. Admin (General Manager)
| Screen/Feature | Access | Authorization |
|---|---|---|
| All conversations | ✅ Full access | `before()` returns true |
| All contacts | ✅ Full access | `getEloquentQuery()` no filter |
| All users/employees | ✅ Full access | `canCreate()` = true |
| All teams | ✅ Full access | `canViewAny()` = true |
| All assignments | ✅ Full access | `getEloquentQuery()` no filter |
| Webhook events | ✅ Full access | `canViewAny()` = true |
| Transfer conversations | ✅ To any user | Policy `transfer()` returns true |
| Close conversations | ✅ Any conversation | Policy `close()` returns true |
| Assign conversations | ✅ To any user | `canAssignChat()` returns true |
| View reports | ✅ Full system reports | Route accessible |
| Manage users | ✅ Can create/edit users | `canCreate()` = true |

### 2. Supervisor
| Screen/Feature | Access | Authorization |
|---|---|---|
| Team conversations | ✅ View only | `getEloquentQuery()` → `whereIn('assigned_to', $memberIds)` |
| Team contacts | ✅ View only | Contact filter by team members |
| Team members | ✅ View only | UserResource → `whereIn('id', $memberIds)` |
| Team assignments | ✅ View only | AssignmentResource → filter by team |
| Transfer conversations | ✅ Within team only | Policy `transferTo()` validates both users in team |
| Close conversations | ✅ Team only | Policy `close()` checks team membership |
| Assign conversations | ✅ To team members only | `canAssignChat()` returns true |
| Team reports | ✅ Team only | Filtered in ChatWorkspaceController |
| Other teams' data | ❌ Blocked | All queries filtered |
| Admin screens | ❌ Hidden | `canViewAny()` returns false |
| Create users | ❌ Blocked | `canCreate()` returns false |

### 3. Agent (Employee)
| Screen/Feature | Access | Authorization |
|---|---|---|
| Own conversations | ✅ View only | `getEloquentQuery()` → `where('assigned_to', $user->id)` |
| Reply to conversations | ✅ Own open chats | Policy `reply()` checks ownership + open status |
| Close conversations | ✅ Own only | Policy `close()` checks ownership |
| Transfer conversations | ❌ Blocked | `canTransferChat()` returns false |
| Assign conversations | ❌ Blocked | `canAssignChat()` returns false |
| Other conversations | ❌ Not visible | All queries filtered by `assigned_to` |
| Team management | ❌ Hidden | NAV_ITEMS roles exclude agent |
| User management | ❌ Hidden | NAV_ITEMS roles exclude agent |
| Webhook events | ❌ Hidden | `canViewAny()` returns false |

## Permission Enforcement

### Backend
- **ConversationPolicy**: All CRUD operations protected
- **Eloquent Scoping**: `getEloquentQuery()` in each Resource filters data
- **ChatWorkspaceController**: Manual role-based filtering for all queries
- **ConversationController**: Transfer validation checks target user permissions
- **MessageController**: Message mutations protected by conversation policy

### Frontend
- **NAV_ITEMS**: Menu items hidden by role
- **Action Buttons**: Transfer/close/assign buttons shown/hidden by `canTransferChat()`, `canCloseChat()`, `canAssignChat()`
- **Details Panel**: Action buttons rendered conditionally
- **Chat List**: Conversations filtered by `getVisibleChats()`

## Protection Against Direct Access
- Direct URL access to unauthorized conversations returns 403
- Direct API requests to unauthorized endpoints blocked
- Supervisor cannot access conversations outside team via URL manipulation
- Agent cannot access other agents' conversations via conversation_id
