Here is the technical specification formatted for a `.md` file:

```markdown
# Feature Management Backend Technical Specification

This document details the database schema and API contract for the Portal Settings Feature Management system.

---

## 1. Database Schema (Prisma)

The feature management model uses a two-table design:
* `FeatureRegistry`: Defines features, labels, categories, and dependencies.
* `FeatureFlag`: Stores instance-specific toggle states and tracks who updated them.

```prisma
// =============================================
// FEATURE FLAGS MODULE
// =============================================

model FeatureRegistry {
  id             Int           @id @default(autoincrement())
  key            String        @unique @db.VarChar(50)
  label          String        @db.VarChar(100)
  category       String?       @db.VarChar(50)
  dependencies   Json?         // Array of feature keys e.g., ["moodleLMS", "payment"]
  defaultEnabled Boolean       @default(false) @map("default_enabled")
  createdAt      DateTime      @default(now()) @map("created_at")
  updatedAt      DateTime      @updatedAt @map("updated_at")
  deletedAt      DateTime?     @map("deleted_at") // Soft delete timestamp

  flags          FeatureFlag[]

  @@map("feature_registry")
}

model FeatureFlag {
  id            Int              @id @default(autoincrement())
  feature       String           @unique @db.VarChar(50) // Matches registry.key
  enabled       Boolean          @default(false)
  updatedBy     Int?             @map("updated_by")
  createdAt     DateTime         @default(now()) @map("created_at")
  updatedAt     DateTime         @updatedAt @map("updated_at")

  updatedByUser User?            @relation(fields: [updatedBy], references: [id])
  registry      FeatureRegistry? @relation(fields: [feature], references: [key])

  @@index([updatedBy])
  @@map("feature_flags")
}

```

---

## 2. API Endpoints Specification

### Registry Management

#### 1. GET `/api/portal-settings/registry`

Retrieves all active feature registry records (filters out soft-deleted entries where `deletedAt` is set).

* **Status:** `200 OK`
* **Response:**

```json
{
  "registry": [
    {
      "id": 1,
      "key": "admission",
      "label": "Admission System",
      "category": "Core",
      "dependencies": [],
      "defaultEnabled": true
    },
    {
      "id": 2,
      "key": "moodleLMS",
      "label": "Moodle LMS Integration",
      "category": "LMS",
      "dependencies": [],
      "defaultEnabled": false
    },
    {
      "id": 3,
      "key": "courseSync",
      "label": "Course Sync",
      "category": "LMS",
      "dependencies": ["moodleLMS"],
      "defaultEnabled": false
    }
  ]
}

```

---

#### 2. POST `/api/portal-settings/registry`

Creates or updates a registry item (upsert based on `key`).

> **Behavior Note:** Automatically creates/updates the corresponding row in `feature_flags` if missing. For new entries, `defaultEnabled` populates the initial flag state.

* **Request Body:**

```json
{
  "key": "liveChat",
  "label": "Live Chat Support",
  "category": "Communication",
  "dependencies": [],
  "defaultEnabled": false
}

```

* **Response (Success - `200 OK`):**

```json
{
  "success": true,
  "registry": {
    "id": 5,
    "key": "liveChat",
    "label": "Live Chat Support",
    "category": "Communication",
    "dependencies": [],
    "defaultEnabled": false,
    "createdAt": "2025-03-15T10:30:00Z",
    "updatedAt": "2025-03-15T10:30:00Z"
  }
}

```

* **Response (Validation Error - `400 Bad Request`):**

```json
{
  "success": false,
  "error": "Validation failed",
  "fieldErrors": {
    "dependencies.0": "Dependency 'unknownFeature' does not exist in registry",
    "key": "Key is required"
  }
}

```

---

#### 3. DELETE `/api/portal-settings/registry/{key}`

Soft-deletes a feature from the registry by updating `deletedAt`. Flags in `feature_flags` are retained for audit history.

* **Response (Success - `200 OK`):**

```json
{
  "success": true,
  "message": "Feature 'liveChat' soft-deleted successfully"
}

```

* **Response (Not Found - `404 Not Found`):**

```json
{
  "success": false,
  "error": "Feature 'liveChat' not found"
}

```

---

### Feature Flag Operations

#### 4. GET `/api/portal-settings/features`

Fetches the current toggle state for all active (non-deleted) registry features.

* **Status:** `200 OK`
* **Response:**

```json
{
  "flags": {
    "admission": true,
    "moodleLMS": false,
    "courseSync": false,
    "liveChat": false
  }
}

```

---

#### 5. POST `/api/portal-settings/features`

Updates feature flag states. Ensures all key dependencies are valid against active registry constraints prior to updating.

* **Request Body:**

```json
{
  "flags": {
    "admission": true,
    "moodleLMS": true,
    "courseSync": true,
    "liveChat": false
  }
}

```

* **Response (Success - `200 OK`):**

```json
{
  "success": true,
  "flags": {
    "admission": true,
    "moodleLMS": true,
    "courseSync": true,
    "liveChat": false
  }
}

```

* **Response (Validation Error - `400 Bad Request`):**

```json
{
  "success": false,
  "error": "Dependency validation failed",
  "fieldErrors": {
    "courseSync": "courseSync depends on moodleLMS",
    "grading": "grading depends on courseSync"
  }
}

```

```

```
