# Access Control Matrix (ACL)

## Role Hierarchy

```
Super Admin (Root Access)
    ├── Developer (Owns Projects)
    │       └── Manages Projects → Units
    │
    ├── Agency (Manages Team)
    │       └── Agents
    │           └── Owns Listings → Leads
    │
    ├── Agent (Independent)
    │       └── Owns Listings → Leads
    │
    └── Customer (End User)
            └── Views → Inquiries → Favorites
```

## Permission Matrix

### Super Admin
| Resource | Create | Read | Update | Delete | Notes |
|----------|--------|------|--------|--------|-------|
| Users | ✅ | ✅ All | ✅ All | ✅ Soft Delete | Full user management |
| Agencies | ✅ | ✅ All | ✅ All | ✅ Soft Delete | Verify RERA/ORN |
| Developers | ✅ | ✅ All | ✅ All | ✅ Soft Delete | Verify trade license |
| Projects | ✅ | ✅ All | ✅ All | ✅ Soft Delete | Moderation capability |
| Units | ✅ | ✅ All | ✅ All | ✅ Soft Delete | Content moderation |
| Subscriptions | ✅ | ✅ All | ✅ All | ✅ Soft Delete | Plan management |
| Subscription Plans | ✅ | ✅ All | ✅ All | ✅ Soft Delete | Pricing control |
| Leads | ✅ | ✅ All | ✅ All | ✅ Soft Delete | Support escalation |
| Webinars | ✅ | ✅ All | ✅ All | ✅ Soft Delete | Platform oversight |
| System Settings | ✅ | ✅ All | ✅ All | ❌ | Platform configuration |
| Audit Logs | ❌ | ✅ All | ❌ | ❌ | Read-only compliance |
| Reports & Analytics | ✅ | ✅ All | ❌ | ❌ | Platform-wide metrics |

### Developer
| Resource | Create | Read | Update | Delete | Notes |
|----------|--------|------|--------|--------|-------|
| Own Profile | ❌ | ✅ Own | ✅ Own | ❌ | Edit company details |
| Own Projects | ✅ | ✅ Own | ✅ Own | ✅ Soft Delete | Unlimited per subscription |
| Own Project Units | ✅ | ✅ Own | ✅ Own | ✅ Soft Delete | All units in projects |
| Other Projects | ❌ | ✅ Public | ❌ | ❌ | View-only competitors |
| Webinars | ✅ | ✅ Own | ✅ Own | ✅ Cancel | Host virtual launches |
| Webinar Registrations | ❌ | ✅ Own | ❌ | ❌ | Attendee data |
| Leads from Webinars | ❌ | ✅ Own | ✅ Own | ❌ | Nurture leads |
| Subscription | ❌ | ✅ Own | ✅ Upgrade/Downgrade | ❌ | Manage billing |
| Analytics | ❌ | ✅ Own | ❌ | ❌ | Project performance |

### Agency
| Resource | Create | Read | Update | Delete | Notes |
|----------|--------|------|--------|--------|-------|
| Own Profile | ❌ | ✅ Own | ✅ Own | ❌ | Agency branding, ORN |
| Team (Agents) | ✅ | ✅ All | ✅ Manage | ✅ Remove | Assign/remove agents |
| Agent Listings | ❌ | ✅ All | ✅ Moderate | ✅ Remove | Control team listings |
| Own Listings | ✅ | ✅ Own | ✅ Own | ✅ Soft Delete | Agency principal listings |
| Leads | ❌ | ✅ All | ✅ Distribute | ❌ | Assign to agents |
| All Agency Leads | ✅ | ✅ All | ✅ All | ✅ Soft Delete | Full pipeline visibility |
| Analytics | ❌ | ✅ Team | ❌ | ❌ | Agent performance |
| Subscription | ❌ | ✅ Own | ✅ Manage | ❌ | Billing, plan limits |
| Webinars | ❌ | ❌ | ❌ | ❌ | Not available for agencies |

### Agent (Agency-affiliated)
| Resource | Create | Read | Update | Delete | Notes |
|----------|--------|------|--------|--------|-------|
| Own Profile | ❌ | ✅ Own | ✅ Own | ❌ | BRN, photo, bio |
| Own Listings | ✅ | ✅ Own | ✅ Own | ✅ Soft Delete | Subject to agency limit |
| Agency Listings | ❌ | ✅ All | ❌ | ❌ | View team listings |
| Assigned Leads | ❌ | ✅ Own | ✅ Own | ❌ | Update status, add notes |
| Other Agent Leads | ❌ | ❌ | ❌ | ❌ | No access |
| Analytics | ❌ | ✅ Own | ❌ | ❌ | Personal performance |
| Subscription | ❌ | ✅ Via Agency | ❌ | ❌ | Agency manages plan |

### Agent (Independent)
| Resource | Create | Read | Update | Delete | Notes |
|----------|--------|------|--------|--------|-------|
| Own Profile | ❌ | ✅ Own | ✅ Own | ❌ | Full profile control |
| Own Listings | ✅ | ✅ Own | ✅ Own | ✅ Soft Delete | Subject to subscription |
| Other Listings | ❌ | ✅ Public | ❌ | ❌ | Browse competitors |
| Leads | ✅ | ✅ Own | ✅ Own | ✅ Soft Delete | Self-managed pipeline |
| Subscription | ❌ | ✅ Own | ✅ Manage | ❌ | Own billing responsibility |
| Webinars | ❌ | ❌ | ❌ | ❌ | Not available for agents |

### Customer
| Resource | Create | Read | Update | Delete | Notes |
|----------|--------|------|--------|--------|-------|
| Own Profile | ❌ | ✅ Own | ✅ Own | ❌ | Basic info |
| Properties | ❌ | ✅ Public | ❌ | ❌ | Search, filter, view |
| Projects | ❌ | ✅ Public | ❌ | ❌ | Browse developments |
| Favorites | ✅ | ✅ Own | ❌ | ✅ Remove | Save properties |
| Inquiries | ✅ | ✅ Own | ❌ | ❌ | Contact agents |
| Webinar Registration | ✅ | ✅ Own | ❌ | ✅ Cancel | Join virtual events |
| Own Leads | ❌ | ✅ Own | ❌ | ❌ | Track inquiry status |

## Field-Level Permissions

### Agency Profile
| Field | Super Admin | Agency Owner | Agent (within agency) |
|-------|-------------|--------------|----------------------|
| Name | ✅ Edit | ✅ Edit | ❌ View Only |
| ORN | ✅ Edit/Verify | ✅ View | ❌ Hidden |
| Trade License | ✅ Edit/Verify | ✅ View | ❌ Hidden |
| Commission Splits | ✅ Edit | ✅ Edit | ❌ Hidden |
| Agent Performance | ✅ View | ✅ View | ❌ View Own Only |
| Billing Info | ✅ Edit | ✅ View/Manage | ❌ Hidden |

### Property Listing (Unit)
| Field | Agent | Agency Admin | Developer |
|-------|-------|-------------|-----------|
| Title/Description | ✅ Full | ✅ Moderate | ✅ Full |
| Price | ✅ Full | ✅ Moderate | ✅ Full |
| RERA Permit | ✅ View/Edit Own | ✅ Verify | ✅ Full |
| Agent Assignment | ❌ | ✅ Reassign | N/A |
| Listing Status | ✅ Toggle | ✅ Override | ✅ Toggle |
| Featured/Premium | ❌ (subscription) | ❌ (subscription) | ✅ Set |
| Analytics | ✅ Own Only | ✅ All Agency | ✅ Own Only |

### Lead Management
| Field | Agent | Agency Admin | Developer |
|-------|-------|-------------|-----------|
| Customer Contact | ✅ Full | ✅ Full | ✅ Webinar Only |
| Lead Status | ✅ Update | ✅ Update/Override | ✅ Update |
| Assignment | ❌ | ✅ Reassign | N/A |
| Notes/Activities | ✅ Add/Edit Own | ✅ View All | ✅ Add Own |
| Deal Value | ✅ Edit | ✅ View All | N/A |

## API Endpoint Access Control

### Public Endpoints (No Auth)
```
GET  /api/properties          - List properties
GET  /api/properties/:id     - Get property details
GET  /api/projects           - List projects
GET  /api/projects/:id       - Get project details
GET  /api/locations          - List locations
GET  /api/amenities          - List amenities
GET  /api/agencies           - List agencies
GET  /api/developers         - List developers
POST /api/contact           - General contact form
```

### Customer Endpoints (Customer+)
```
GET    /api/me/favorites          - List favorites
POST   /api/me/favorites          - Add favorite
DELETE /api/me/favorites/:id     - Remove favorite
POST   /api/inquiries             - Create inquiry
GET    /api/me/inquiries          - List my inquiries
GET    /api/me/leads              - List leads as customer
POST   /api/webinars/:id/register - Register for webinar
```

### Agent Endpoints (Agent+)
```
GET    /api/agent/listings        - My listings
POST   /api/agent/listings        - Create listing
PUT    /api/agent/listings/:id    - Update my listing
DELETE /api/agent/listings/:id    - Delete my listing
GET    /api/agent/leads           - My assigned leads
PUT    /api/agent/leads/:id       - Update lead status
POST   /api/agent/leads/:id/notes - Add lead note
GET    /api/agent/analytics       - My performance stats
```

### Agency Admin Endpoints (Agency+)
```
GET    /api/agency/dashboard      - Agency overview
GET    /api/agency/agents         - Manage team
POST   /api/agency/agents         - Add agent
DELETE /api/agency/agents/:id     - Remove agent
GET    /api/agency/listings       - All agency listings
PUT    /api/agency/listings/:id   - Moderate listing
GET    /api/agency/leads          - All agency leads
POST   /api/agency/leads/assign   - Assign lead to agent
GET    /api/agency/analytics      - Team performance
PUT    /api/agency/settings       - Agency settings
```

### Developer Endpoints (Developer+)
```
GET    /api/dev/projects          - My projects
POST   /api/dev/projects          - Create project
PUT    /api/dev/projects/:id      - Update project
GET    /api/dev/projects/:id/units - List project units
POST   /api/dev/units             - Create unit
PUT    /api/dev/units/:id         - Update unit
GET    /api/dev/webinars          - My webinars
POST   /api/dev/webinars          - Schedule webinar
PUT    /api/dev/webinars/:id      - Manage webinar
GET    /api/dev/leads             - Project leads
GET    /api/dev/analytics         - Project analytics
```

### Admin Endpoints (Super Admin)
```
GET    /api/admin/users           - All users
PUT    /api/admin/users/:id       - Manage user
DELETE /api/admin/users/:id       - Suspend user
GET    /api/admin/agencies        - All agencies
PUT    /api/admin/agencies/:id/verify - Verify ORN
GET    /api/admin/developers      - All developers
GET    /api/admin/properties      - All properties
PUT    /api/admin/properties/:id/moderate - Moderate
GET    /api/admin/subscriptions   - All subscriptions
PUT    /api/admin/subscriptions/:id - Manage
GET    /api/admin/audit-logs      - System audit
GET    /api/admin/analytics       - Platform analytics
PUT    /api/admin/settings        - System settings
```

## Middleware Implementation

### Role Check Middleware
```javascript
// middleware/authorize.js
const authorize = (allowedRoles) => {
  return (req, res, next) => {
    const userRole = req.user.primary_role;
    
    if (!allowedRoles.includes(userRole)) {
      return res.status(403).json({ 
        error: 'Access denied. Insufficient permissions.' 
      });
    }
    
    next();
  };
};

// Usage
router.get('/admin/users', 
  authenticate, 
  authorize(['super_admin']), 
  getAllUsers
);
```

### Resource Ownership Middleware
```javascript
// middleware/ownership.js
const checkOwnership = (resourceType) => {
  return async (req, res, next) => {
    const { id } = req.params;
    const userId = req.user.id;
    const role = req.user.primary_role;
    
    // Super admin bypass
    if (role === 'super_admin') return next();
    
    const resource = await getResource(resourceType, id);
    
    // Check ownership based on resource type
    let isOwner = false;
    
    switch(resourceType) {
      case 'unit':
        isOwner = resource.agent_id === userId ||
                  (role === 'agency' && resource.agency_id === req.user.agency_id);
        break;
      case 'lead':
        isOwner = resource.assigned_to_agent_id === userId ||
                  (role === 'agency' && resource.assigned_to_agency_id === req.user.agency_id);
        break;
      case 'project':
        isOwner = resource.developer_id === req.user.developer_id;
        break;
    }
    
    if (!isOwner) {
      return res.status(403).json({ 
        error: 'Access denied. Not resource owner.' 
      });
    }
    
    req.resource = resource;
    next();
  };
};
```

### Subscription Check Middleware
```javascript
// middleware/subscription.js
const checkSubscription = (requiredFeature) => {
  return async (req, res, next) => {
    const subscription = await getActiveSubscription(req.user.id);
    
    if (!subscription || subscription.status !== 'active') {
      return res.status(403).json({ 
        error: 'Active subscription required.' 
      });
    }
    
    const plan = await getPlan(subscription.plan_id);
    const features = JSON.parse(plan.features_json);
    
    if (!features[requiredFeature]) {
      return res.status(403).json({ 
        error: `Your plan does not include ${requiredFeature}.` 
      });
    }
    
    // Check usage limits
    if (subscription.listings_used >= plan.max_listings) {
      return res.status(403).json({ 
        error: 'Listing limit reached. Please upgrade your plan.' 
      });
    }
    
    next();
  };
};
```

## Frontend Route Guards

### Next.js Middleware
```typescript
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

const roleRoutes = {
  '/admin': ['super_admin'],
  '/agency': ['agency'],
  '/agent': ['agent', 'agency'], // Agency can access agent views
  '/developer': ['developer'],
  '/customer': ['customer', 'agent', 'agency', 'developer'], // All can access
};

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token')?.value;
  const path = request.nextUrl.pathname;
  
  // Check role-based access
  for (const [routePrefix, allowedRoles] of Object.entries(roleRoutes)) {
    if (path.startsWith(routePrefix)) {
      // Verify JWT and check role
      // Redirect to unauthorized if role doesn't match
    }
  }
  
  return NextResponse.next();
}
```

## Audit Requirements

All access control decisions are logged:
- **Timestamp**: When access was attempted
- **User**: Who attempted access
- **Resource**: What was accessed
- **Action**: CRUD operation
- **Result**: Success/Denied
- **Reason**: If denied, specific policy violation
