# Review Mark API 規格

## 概述

Review Mark（審閱標記）功能允許使用者針對**控制項（Control）**或**評估項目（Assessment Object / AO）**進行簽署確認（Sign-off）。

- 審閱紀錄為**整個專案共用**，所有專案成員均可看到誰已審閱。
- 同一控制項 / AO 可由多位使用者分別簽署。
- POST 為冪等操作（已審閱則不重複新增）；DELETE 只移除當前使用者自己的標記。

---

## 1. 標記控制項已審閱

```
POST /api/1.0/grc/project/:project_uid/control/:control_uid/review
```

### Headers

| Header | Value |
|---|---|
| Authorization | Bearer {token} |
| Content-Type | application/json |

### Path Parameters

| 參數 | 型別 | 說明 |
|---|---|---|
| project_uid | string | 專案 UID |
| control_uid | string | 控制項 UID（OscalAssessmentPlanControl.uid） |

### Response 200

```json
{
  "status": true,
  "data": {
    "is_reviewed": true,
    "reviewers": [
      {
        "uid": "user-uid-001",
        "name": "Alex Wang",
        "reviewed_at": "2026-03-12T10:30:00"
      }
    ]
  }
}
```

---

## 2. 取消控制項審閱標記

```
DELETE /api/1.0/grc/project/:project_uid/control/:control_uid/review
```

### Headers

同上。

### Path Parameters

同上。

### Response 200

```json
{
  "status": true,
  "data": {
    "is_reviewed": false,
    "reviewers": []
  }
}
```

---

## 3. 標記評估項目已審閱

```
POST /api/1.0/grc/project/:project_uid/control/:control_uid/ao/:ao_uid/review
```

### Path Parameters

| 參數 | 型別 | 說明 |
|---|---|---|
| project_uid | string | 專案 UID |
| control_uid | string | 控制項 UID |
| ao_uid | string | 評估項目 UID（OscalAssessmentPlanTask.uid） |

### Response 200

```json
{
  "status": true,
  "data": {
    "is_reviewed": true,
    "reviewers": [
      {
        "uid": "user-uid-001",
        "name": "Alex Wang",
        "reviewed_at": "2026-03-12T10:30:00"
      }
    ]
  }
}
```

---

## 4. 取消評估項目審閱標記

```
DELETE /api/1.0/grc/project/:project_uid/control/:control_uid/ao/:ao_uid/review
```

### Response 200

```json
{
  "status": true,
  "data": {
    "is_reviewed": false,
    "reviewers": []
  }
}
```

---

## 5. 審閱資料整合進現有 API

### 5.1 GET /api/1.0/grc/project/:uid

新增欄位 `reviewed_controls_count`（整個專案中已被至少一人審閱的控制項數量）。

```json
{
  "status": true,
  "data": {
    "id": "project-uid",
    "name": "CMMC L2 2024",
    "total_controls": 110,
    "reviewed_controls_count": 35,
    ...
  }
}
```

### 5.2 POST /api/1.0/grc/project/:project_id/control-groups/list

每筆 control group 新增 `reviews` 物件：

```json
{
  "status": true,
  "data": [
    {
      "id": "group-uid",
      "name": "Access Control",
      "total_controls": 22,
      "reviews": {
        "reviewed_controls_count": 10,
        "reviewed_ao_count": 15,
        "control_reviews": [
          {
            "control_uid": "ctrl-uid-001",
            "control_code": "AC.1.001",
            "reviewers": [
              {
                "uid": "user-uid-001",
                "name": "Alex Wang",
                "reviewed_at": "2026-03-12T10:30:00"
              }
            ]
          }
        ],
        "ao_reviews": [
          {
            "ao_uid": "ao-uid-001",
            "control_uid": "ctrl-uid-001",
            "reviewers": [
              {
                "uid": "user-uid-001",
                "name": "Alex Wang",
                "reviewed_at": "2026-03-12T10:30:00"
              }
            ]
          }
        ]
      }
    }
  ],
  "meta": { ... }
}
```

### 5.3 POST /api/1.0/grc/project/:project_uid/control-group/:group_uid/controls/list

每筆 control 新增 `is_reviewed` 和 `reviewers`；每筆 assessment_objects 也新增 `is_reviewed` 和 `reviewers`：

```json
{
  "status": true,
  "data": [
    {
      "id": "ctrl-uid-001",
      "code": "AC.1.001",
      "name": "Limit system access...",
      "is_reviewed": true,
      "reviewers": [
        {
          "uid": "user-uid-001",
          "name": "Alex Wang",
          "reviewed_at": "2026-03-12T10:30:00"
        }
      ],
      "assessment_objects": [
        {
          "uid": "ao-uid-001",
          "title": "Examine: ...",
          "is_reviewed": false,
          "reviewers": [],
          "jobs": [...]
        }
      ]
    }
  ],
  "meta": { ... }
}
```

---

## 資料庫

表：`compliance.review_marks`

| 欄位 | 型別 | 說明 |
|---|---|---|
| id | SERIAL PK | |
| project_id | INTEGER | 專案 ID |
| group_id | INTEGER | 控制群組 ID |
| control_id | INTEGER | 控制項 ID |
| ao_id | INTEGER NULL | NULL = 控制項層級; 有值 = AO 層級 |
| user_id | INTEGER | 審閱者 ID |
| reviewed_at | TIMESTAMP | 審閱時間 |

Unique indexes：
- `uq_review_control (project_id, control_id, user_id) WHERE ao_id IS NULL`
- `uq_review_ao (project_id, control_id, ao_id, user_id) WHERE ao_id IS NOT NULL`

Migration：`scripts/sql/add_review_marks.sql`
