# GRC 多輪稽核架構變更 — 前端溝通規格書

> 日期：2026-03-24
> 狀態：Draft — 待前後端確認

---

## 一、為什麼要改？

目前系統假設「一個專案 = 一個 Assessment Plan（AP）」，所有 GRC API 都用 `project_uid` 去查唯一的一組控制項資料。

但實際業務需求是：**一個專案會經歷多輪稽核**（每年一次），每一輪都有自己獨立的控制項結構、任務、證據、稽核結果。所以需要改為「一個專案 = 多個 AP」，每個 AP 代表一輪稽核。

---

## 二、使用者流程變更

### 現在的流程

```
專案列表 → 點進專案 → 直接看到控制項群組 / 任務設定 / Dashboard
```

### 改後的流程

```
專案列表 → 點進專案 → 選擇稽核輪次（AP） → 看到該輪的控制項群組 / 任務 / 稽核結果
                         ↑
                    新增的一步：選擇 AP
```

前端進入專案後需要多一個「稽核輪次選擇」的步驟（或預設選最新的 AP）。

---

## 三、新增的頁面 / 元件

### 3.1 稽核輪次選擇

**進入時機：** 點進專案後、進入控制項列表前

**資料來源：** `GET /grc/project/<project_uid>/assessment-plans/menu`

**回傳格式：**
```json
[
  {
    "uid": "ap-uuid-001",
    "name": "2025 年度稽核",
    "round_number": 1,
    "status": "closed",
    "created_at": "2025-03-15T00:00:00"
  },
  {
    "uid": "ap-uuid-002",
    "name": "2026 年度稽核",
    "round_number": 2,
    "status": "in_progress",
    "created_at": "2026-02-20T00:00:00"
  }
]
```

**AP status 值：**

| status | 顯示 | 說明 |
|--------|------|------|
| `active` | 進行中 | Phase 1+2：任務指派 + 執行 |
| `auditing` | 稽核中 | Phase 3：外部稽核員審查 |
| `remediation` | 矯正中 | Phase 4：補件矯正 |
| `closed` | 已結案 | 本輪完成 |

**建議 UI：**
- 下拉選單 或 Tab 切換
- 預設選中 status 不是 `closed` 的那筆（最新進行中的）
- 如果全部 closed，選最新的（round_number 最大）
- `closed` 的 AP 進入後為唯讀模式

### 3.2 Phase 3 稽核頁面（未來 Stage 2 實作）

稽核人員專用介面，逐控制項寫入 verdict + findings。Phase 3 的前端規格會在 Stage 2 開始前另行提供。

### 3.3 POA&M 追蹤頁面（未來 Stage 3 實作）

矯正階段的追蹤總覽。Stage 3 開始前另行提供。

---

## 四、API URL 變更（Stage 1）

### 核心變更：URL 加入 `ap/<ap_uid>` 路徑段

所有需要查詢控制項結構的 API，URL 從：

```
/api/1.0/grc/project/<project_uid>/...
```

改為：

```
/api/1.0/grc/project/<project_uid>/ap/<ap_uid>/...
```

### 變更對照表

| 功能 | 現有 URL | 新 URL |
|------|---------|--------|
| Control Groups 列表 | `POST .../project/{pid}/control-groups/list` | `POST .../project/{pid}/ap/{ap}/control-groups/list` |
| Control Group 詳情 | `GET .../project/{pid}/control-group/{gid}` | `GET .../project/{pid}/ap/{ap}/control-group/{gid}` |
| Controls 列表 | `POST .../project/{pid}/control-group/{gid}/controls/list` | `POST .../project/{pid}/ap/{ap}/control-group/{gid}/controls/list` |
| Control 詳情 | `GET .../project/{pid}/control-group/{gid}/control/{cid}` | `GET .../project/{pid}/ap/{ap}/control-group/{gid}/control/{cid}` |
| Control + AO 詳情 | `GET .../project/{pid}/control-group/{gid}/control/{cid}/detail` | `GET .../project/{pid}/ap/{ap}/control-group/{gid}/control/{cid}/detail` |
| AO 列表 | `POST .../project/{pid}/control-group/{gid}/control/{cid}/assessment-objects/list` | `POST .../project/{pid}/ap/{ap}/control-group/{gid}/control/{cid}/assessment-objects/list` |
| Job 列表 | `POST .../project/{pid}/.../assessment-object/{ao}/jobs/list` | `POST .../project/{pid}/ap/{ap}/.../assessment-object/{ao}/jobs/list` |
| Job 新增 | `POST .../project/{pid}/assessment-object/{ao}/jobs` | `POST .../project/{pid}/ap/{ap}/assessment-object/{ao}/jobs` |
| Task Setup 樹 | `GET .../project/{pid}/task-setup/tree` | `GET .../project/{pid}/ap/{ap}/task-setup/tree` |
| Control 審核 | `POST/DELETE .../project/{pid}/control/{cid}/review` | `POST/DELETE .../project/{pid}/ap/{ap}/control/{cid}/review` |
| AO 審核 | `POST/DELETE .../project/{pid}/control/{cid}/ao/{ao}/review` | `POST/DELETE .../project/{pid}/ap/{ap}/control/{cid}/ao/{ao}/review` |

### 不變的 API

以下 API **不需要改**，前端不用調整：

| 功能 | URL | 原因 |
|------|-----|------|
| 專案列表 | `POST /grc/projects/list` | 專案層級，不涉及 AP |
| 專案選單 | `GET /grc/projects/menu` | 同上 |
| 專案詳情 | `GET /grc/project/{uid}` | 同上 |
| 專案更新 | `PUT /grc/project/{uid}` | 同上 |
| 專案刪除 | `DELETE /grc/project/{uid}` | 同上 |
| My Jobs | `POST /grc/jobs/my/list` | 透過 workflow_execution 直查 |
| Job 詳情 | `GET /grc/project/{pid}/job/{job_uid}` | by job_uid 直查 |
| Job 更新 | `PUT /grc/project/{pid}/job/{job_uid}` | by job_uid 直查 |
| Job 刪除 | `DELETE /grc/project/{pid}/job/{job_uid}` | by job_uid 直查 |
| Job 完成 | `POST /flow-engine/task/complete/{id}` | by workflow_execution_uid |
| Job 退回 | `POST /flow-engine/task/revert/{id}` | by workflow_execution_uid |
| Job Comment CRUD | `/grc/job-executions/{uid}/comments` | by job_execution_uid |
| Job Evidence CRUD | `/flow-engine/job-evidences` | by job_execution_uid |
| 參與者 CRUD | `/project-participant`, etc. | by project_id |
| SSP 編輯 | `/ssp/{ssp_uid}/control-implementation/...` | by ssp_uid |
| Dashboard | `GET /grc/dashboard/summary` | 後端自動取最新 AP |

### 向下相容

過渡期間，如果 `ap_uid` 未帶，後端會自動 fallback 取該專案最新的 AP。但建議前端盡快遷移到新 URL。

---

## 五、新增 API（Stage 1）

### 5.1 AP 列表

```
GET /api/1.0/grc/project/<project_uid>/assessment-plans/menu
```

**Response：**
```json
{
  "code": 1,
  "data": [
    {
      "uid": "string",
      "name": "string",
      "round_number": 1,
      "status": "active | auditing | remediation | closed",
      "created_at": "2025-03-15T00:00:00"
    }
  ]
}
```

---

## 六、前端路由建議

### 現有路由結構（推測）

```
/grc/projects                              → 專案列表
/grc/project/:projectUid                   → 專案詳情
/grc/project/:projectUid/task-setup        → 任務設定
/grc/project/:projectUid/control-groups    → 控制項群組
/grc/project/:projectUid/control-group/:groupUid/controls  → 控制項
...
```

### 建議調整

```
/grc/projects                              → 專案列表（不變）
/grc/project/:projectUid                   → 專案詳情（不變）
/grc/project/:projectUid/rounds            → 稽核輪次列表（新增，或整合在專案詳情頁）
/grc/project/:projectUid/ap/:apUid/task-setup
/grc/project/:projectUid/ap/:apUid/control-groups
/grc/project/:projectUid/ap/:apUid/control-group/:groupUid/controls
/grc/project/:projectUid/ap/:apUid/control-group/:groupUid/control/:controlUid
...
```

關鍵：URL 中加入 `ap/:apUid`，讓每個頁面知道當前在看哪一輪稽核。

---

## 七、狀態與顯示對照

### 專案列表 — project.status

| status | 中文 | 英文 | Badge 顏色建議 |
|--------|------|------|---------------|
| `pending` | 未開始 | Pending | 灰色 |
| `in_progress` | 進行中 | In Progress | 藍色 |
| `completed` | 已完成 | Completed | 綠色 |
| `suspended` | 已暫停 | Suspended | 黃色 |
| `archived` | 已封存 | Archived | 灰色 |

### AP 輪次 — AP status（phase）

| status | 中文 | 英文 | Badge 顏色建議 |
|--------|------|------|---------------|
| `active` | 進行中 | Active | 藍色 |
| `auditing` | 稽核中 | Auditing | 橘色 |
| `remediation` | 矯正中 | Remediation | 紅色 |
| `closed` | 已結案 | Closed | 綠色 |

### POA&M 狀態（Phase 4，未來實作）

| status | 中文 | 英文 |
|--------|------|------|
| `open` | 待處理 | Open |
| `in_progress` | 矯正中 | In Progress |
| `closed` | 已關閉 | Closed |

### AR Verdict（Phase 3，未來實作）

| verdict | 中文 | 英文 |
|---------|------|------|
| `pass` | 通過 | Pass |
| `fail` | 不通過 | Fail |
| `partial` | 部分通過 | Partial |
| `na` | 不適用 | N/A |

---

## 八、實作時程（後端）

| 階段 | 內容 | 前端影響 |
|------|------|---------|
| **Stage 1** | API URL 加 `ap_uid` + AP 列表 API + 向下相容 | **前端需配合調整路由和 API 呼叫** |
| **Stage 2** | Phase 3 外部稽核（launch_audit、AR CRUD、confirm_audit） | 新頁面：稽核員操作介面 |
| **Stage 3** | Phase 4 矯正（POA&M 列表、close-round） | 新頁面：POA&M 追蹤 |
| **Stage 4** | 多輪稽核（launch_new_round、歷史瀏覽） | 新功能：開啟新輪次按鈕 |

Stage 1 完成後前端可以先行遷移 URL，後續 Stage 2-4 會逐步提供新頁面的規格。

---

## 九、遷移 Checklist（前端）

Stage 1 上線後，前端需要：

- [ ] 呼叫 AP 列表 API，在專案詳情頁 or 側邊欄顯示稽核輪次選擇
- [ ] 將選中的 `apUid` 存入路由 params 或狀態管理
- [ ] 更新以下頁面的 API 呼叫，URL 加入 `/ap/{apUid}`：
  - [ ] Task Setup 頁
  - [ ] Control Groups 列表頁
  - [ ] Control Group 詳情頁
  - [ ] Controls 列表頁
  - [ ] Control 詳情頁
  - [ ] Control + AO 詳情頁
  - [ ] AO 列表頁
  - [ ] Job 列表頁
  - [ ] Job 新增
  - [ ] Control Review（sign-off）
  - [ ] AO Review
- [ ] 確認以下頁面不需要改：
  - [ ] 專案列表 / 詳情 / 更新
  - [ ] My Jobs
  - [ ] Job 詳情 / 更新 / 刪除
  - [ ] Job Comment
  - [ ] Job Evidence
  - [ ] SSP 編輯
  - [ ] Dashboard

---

## 十、Q&A

**Q: 現有專案只有一個 AP，遷移後怎麼辦？**
A: 不需要做資料遷移。AP 列表 API 會回傳該專案唯一的那筆 AP，前端選中它即可。向下相容邏輯也會自動 fallback。

**Q: 選定 AP 後，AP 的 status 會影響哪些操作？**
A: 後端會根據 AP status 限制操作權限（例如 `closed` 狀態不能新增 job、不能修改 review）。前端可以依據 AP status 決定是否顯示編輯按鈕。

**Q: Dashboard 要不要也分 AP？**
A: 第一階段 Dashboard 維持現有邏輯（自動取最新 AP），不需要帶 `ap_uid`。未來可能加 AP 篩選。

**Q: My Jobs 頁面要不要顯示是哪一輪的任務？**
A: My Jobs 回傳資料已包含 `project_name`，未來會加上 `round_number` 或 `ap_name` 欄位讓前端顯示。
