# Module Permission System Overview

This document describes how the module permission system works, including how module access is determined for users in the current system using programs and enrollments.

## Resource Structure

The system uses a hierarchical structure for module management:

### 1. `modules` - Core Module Table
Stores all available modules in the system.

| Column          | Type      | Description              |
|-----------------|-----------|--------------------------|
| module_id       | UUID      | Primary key              |
| parent_module_id| UUID      | Parent module reference  |
| name            | VARCHAR   | Module name              |
| config          | JSONB     | Module configuration     |
| org_id          | UUID      | Direct org assignment    |
| icon            | VARCHAR   | Module icon              |
| description     | TEXT      | Module description       |
| updatedAt       | TIMESTAMP | Last updated timestamp   |
| isDeleted       | BOOLEAN   | Soft delete flag         |

### 2. `programs` - Program Table
Groups modules into programs that can be assigned to organizations.

| Column          | Type      | Description                    |
|-----------------|-----------|--------------------------------|
| program_id      | UUID      | Primary key                    |
| name            | TEXT      | Program name                   |
| owner_root_org_id| UUID     | Owner organization            |
| is_private      | BOOLEAN   | Private/public program         |
| updatedAt       | TIMESTAMP | Last updated timestamp         |
| isDeleted       | BOOLEAN   | Soft delete flag               |

### 3. `program_modules` - Program-Module Link
Links modules to programs.

| Column          | Type      | Description              |
|-----------------|-----------|--------------------------|
| program_module_id| UUID     | Primary key              |
| program_id      | UUID      | Program reference        |
| module_id       | UUID      | Module reference         |
| config_json     | JSONB     | Module config override   |
| updatedAt       | TIMESTAMP | Last updated timestamp   |
| isDeleted       | BOOLEAN   | Soft delete flag         |

### 4. `program_enrollments` - Program-Org Link
Links organizations to programs.

| Column              | Type      | Description              |
|---------------------|-----------|--------------------------|
| program_enrollment_id| UUID     | Primary key              |
| program_id          | UUID      | Program reference        |
| org_id              | UUID      | Organization reference   |
| status              | TEXT      | Enrollment status        |
| enrolled_at         | TIMESTAMP | Enrollment timestamp     |
| updatedAt           | TIMESTAMP | Last updated timestamp   |
| isDeleted           | BOOLEAN   | Soft delete flag         |

### 5. `orgs` - Organization Table
Stores organization hierarchy.

| Column          | Type      | Description              |
|-----------------|-----------|--------------------------|
| org_id          | UUID      | Primary key              |
| parent_org_id   | UUID      | Parent org reference     |
| root_org_id     | UUID      | Root org reference       |
| name            | TEXT      | Organization name        |
| kind            | TEXT      | Org type                 |
| path            | LTREE     | Hierarchy path           |
| custom_domain   | TEXT      | Custom domain            |
| updatedAt       | TIMESTAMP | Last updated timestamp   |
| isDeleted       | BOOLEAN   | Soft delete flag         |

## How Modules are Added to Organizations

Modules can be added to organizations in two ways:

### 1. Direct Assignment
Modules can be directly assigned to an organization by setting the `org_id` field in the `modules` table.

### 2. Through Programs
- Create a program containing multiple modules via `program_modules`
- Enroll organizations in the program via `program_enrollments`
- Organizations gain access to all modules in enrolled programs

## Permissions Model

Permissions are stored in the `permissions` table with the following structure:

- `resource_type_id`: Type of resource ('module', 'program', etc.)
- `resource_name`: Name of the module/program
- `subject_type`: 'org', 'user', 'role'
- `subject_id`: ID of the org, user, or role
- `can_view`, `can_edit`, `can_delete`, `can_create`: Permission flags
- `conditions_json`: Optional conditions

## Permission Resolution Flow

Permissions are resolved in precedence order:

Organization < Role < User

Permissions are merged according to:
- true (allow) overrides null
- false (deny) overrides everything
- null is treated as unspecified

## Permissions Model

All permissions are stored in the `permissions` table. Each permission entry includes:

- `resource_type_id`: The type of resource (e.g., 'module', 'program')
- `resource_name`: The unique name of the module or program
- `subject_type`: 'org', 'user', or 'role'
- `subject_id`: ID of the org, user, or role
- `can_view`, `can_edit`, `can_delete`, `can_create`: Tri-state booleans (true, false, null)
- `conditions_json`: Optional conditional metadata

## Permission Resolution Flow

Permissions are resolved in precedence order:

Organization < Role < User

Permissions are merged according to the following rules:

- true (allow) overrides null
- false (deny) overrides everything
- null is treated as unspecified

## getPermissions()

Before using `getAllowedModules()`, the class must call:

```php
$this->getPermissions();
```

This internally calls `getEffectivePermissions('module', ...)` which resolves and merges all module-level permissions into:

```php
$this->permissions->modules = (object)[
  'case_management' => (object)['can_view' => true, ...],
  'finance' => (object)['can_view' => false, ...],
];
```

## getAllowedModules()

This function returns the list of module names that the user is allowed to view.

### Logic:

1. Gets all modules available to the user's organizations (via direct assignment or program enrollment)
2. If `userId === 1` (superadmin), returns all available modules
3. Otherwise:
   - Loads `this->permissions->modules`
   - Filters for `can_view === true`
   - Returns the final allowed list of module names

### Code:

```php
public function getAllowedModules(int $userId): array
```

### Output Example:

```php
[
  "case_management",
  "finance",
  "inventory"
]
```

## Usage Notes

- Permissions are based on `resource_name` from the `modules` table
- Modules can be assigned directly to orgs or through programs
- Program enrollment gives org access to all modules in that program
- The system supports hierarchical org structures with permission inheritance