# FR-038 — 前端遷移到 audit-round 新引擎 實作計畫

> 範圍：把專案/稽核生命週期的 FE 從舊 `/grc/project/<uid>/ap/<uid>/*` 引擎，遷到新的
> **audit-round（稽核輪次）引擎**（`/oscal-project/start`、`/projects/<id>/audit-rounds/*`、
> `/audit-round/<id>/*`、`/ap/<id>/*`、`/ar/*`、`/poam*`）。
> **原則**：大部分 FE 沿用，只動 4 塊；漸進式、每 Step 可獨立 ship + 手測。
> 撰寫日：2026-06-16　BE 端新引擎 API 已上線（見 [`fr038-api-inventory.md`](fr038-api-inventory.md) §3）。

## 0. 已拍板決策

| # | 決策 | 影響 |
|---|------|------|
| **D1** | 路由參數從 `apUid` 改為 **`roundUid`**（新引擎輪次為核心；AP 沿 engagement 多輪共用）| 所有 ap-scoped route + 麵包屑 `meta.breadcrumb.parent` + 側欄高亮要跟著改 |
| **D2** | 舊 `/grc/project/ap` 引擎**漸進退場**：新 view 全接新 API；舊 route 先留但**拔掉入口**（避免使用者誤入依賴退役表的舊 AR/task-setup）；全綠後再刪舊 route + service | 過渡期新舊並存，但使用者只走得到新的 |

## 1. 範圍總表

| 區塊 | 現行檔 | 動作 | 難度 |
|------|--------|------|------|
| ① Audit Round 列表 | `ProjectApListView.vue` | **重構**（AP 清單 → 輪次清單）| 中 |
| ② AP 維護 | （無）| **新建** | 大 |
| ③ AR 維護 | `AuditReviewView.vue` + `AuditVerdictPanel.vue` | **重構**（控制項層 → AO 層 + risk）| 大 |
| ④ POA&M | `PoamView.vue` + `PoamDetailDrawer.vue` | **重構**（扁平 → 三層）| 中大 |
| 保留 | MyTasksView / TaskSetupView / RoundSwitcherBar / AuditTreeNav / AuditControlRef / FlowPhaseBanner / StatusBadge / JobExecutionDrawer | 驗證即可 | 小 |

---

## Step 0 — 地基（先做）

**目標**：常數 + 路由 + 輪次切換器就位，讓後續 Step 有地基。

- `src/config/api/api.js`：新增端點常數
  - `OSCAL_PROJECT_START` = `/oscal-project/start`
  - `AUDIT_ROUNDS` = `/projects`（+ `/<id>/audit-rounds[/list]`）
  - `AUDIT_ROUND` = `/audit-round`（+ `/<id>` + 動詞 `/launch-audit|launch-reverify|start-auditing|close-round`）
  - `AP` = `/ap`（+ `/<id>/reviewed-controls|assessment-subjects|tasks`）、`AUDIT_ROUND_AP` = `/audit-round/<id>/ap[/generate-draft]`
  - `AR_FINDINGS` `/audit-round/<id>/ar/findings`、`AR_FINDING` `/ar/finding/<id>`、`AR_RISKS` `/audit-round/<id>/ar/risks`、`AR_RISK_FINDINGS` `/ar/risk/<id>/findings`、`AR_OBSERVATIONS`、`AR_FINALIZE`
  - `POAM_ITEMS` `/audit-round/<id>/poam-items`、`POAM_ITEM` `/poam-item/<id>`、`REMEDIATION_MILESTONES` `/remediation/<id>/milestones`、`POAM_MILESTONE` `/poam-milestone/<id>`
- `src/config/router/index.js`：新增 round-scoped route（D1）
  - `/project/projects/:id/round/:roundUid/{plan,audit,poam}` 等；舊 `:apUid` route 先留（D2）
  - `menu.json` 補新 route name；`meta.breadcrumb[0].parent` 指對 owning 列表頁
- `RoundSwitcherBar.vue`：改接 `POST /projects/<id>/audit-rounds/list`（payload 對齊 round_no / status / parent）
- **驗收**：常數可 import、新 route 可進（空殼）、RoundSwitcher 能列輪次。

## Step 1 — ① Audit Round 列表（重構，中）

**目標**：`ProjectApListView` 改成列輪次 + 生命週期動詞按鈕。

- 改 `ProjectApListView.vue`：
  - 列表來源 → `POST /projects/<id>/audit-rounds/list`；欄位 round_type / status（七態）/ parent 血緣 / start_at
  - 「建輪次」→ `POST /projects/<id>/audit-rounds`（initial / surveillance）
  - **按鈕可用性改用 `round.status` 七態**（取代舊 flow stage 判斷）：
    - `planning` → 啟動稽核 `POST /audit-round/<id>/launch-audit`
    - `audit_planning` → 進 AP 維護（Step 2）
    - `auditing` → 進 AR 維護（Step 3）；`start-auditing` 動詞
    - `remediation` → POA&M（Step 4）
    - `pending_reverify` → 發起覆核 `launch-reverify`
    - `closed` → 唯讀
- **驗收**：建輪次 / launch-audit / 狀態正確顯示 / 各狀態按鈕正確。

## Step 2 — ② AP 維護（新建，大）

**目標**：launch-audit 後，稽核員編 AP 的全新畫面。

- 新 view `AuditPlanView.vue`（route `/round/:roundUid/plan`）：
  - 載入 `GET /audit-round/<id>/ap`；可 `POST .../ap/generate-draft` 重生
  - 三區塊：
    - **查核控制項**：`PUT /ap/<id>/reviewed-controls`（可重用 `AuditTreeNav` 當控制項勾選器）
    - **抽查名單**：`PUT /ap/<id>/assessment-subjects`（subject_type ∈ component/inventory-item/location/party/user，全量覆寫）
    - **行程 + 方法**：`PUT /ap/<id>/tasks`（timing + methods EXAMINE/INTERVIEW/TEST）
- **驗收**：草稿載入 / 三區塊存檔 / 重生草稿。

## Step 3 — ③ AR 維護（重構，大）

**目標**：`AuditReviewView` 判定下沉到 AO 層 + 新增 risk。

- 改 `AuditReviewView.vue` + `AuditVerdictPanel.vue`：
  - 矩陣來源 → `GET /audit-round/<id>/ar/findings`（控制項導覽 + 展開 AO；每 AO 一筆 finding）
  - **AuditVerdictPanel 重構**：從單一 control verdict → **AO 逐項判定**（`PUT /ar/finding/<id>`，met/not_met/pending）
  - observation：`POST /audit-round/<id>/ar/observations`
- **新增 `RiskPanel.vue`**：
  - 列表/建立 `GET|POST /audit-round/<id>/ar/risks`（severity low/medium/high/critical）
  - 組風險：`PUT /ar/risk/<id>/findings`（多對多勾 finding，全量覆寫）
- finalize：`POST /audit-round/<id>/ar/finalize` → 無 not_met 結案 / 有 not_met 轉 remediation + 自動生 POA&M
- 可留：RoundSwitcherBar / AuditTreeNav / AuditControlRef / FlowPhaseBanner / PreviousFindingsPanel
- **驗收**：AO 逐項判定 / 建風險 + 關聯 finding / finalize 兩條路徑（closed vs remediation）。

## Step 4 — ④ POA&M（重構，中大）

**目標**：`PoamView` 從扁平改成三層。

- 改 `PoamView.vue` + `PoamDetailDrawer.vue`：
  - item 列表 `POST /audit-round/<id>/poam-items/list`（讀 `deadline_warning` / `days_remaining`，BE 已回）
  - item 詳情 `GET /poam-item/<id>`（封面 + risk/remediation/milestone）
  - 整改計畫 `POST /ar/risk/<id>/remediations`
  - 里程碑 `POST /remediation/<id>/milestones`、`PUT /poam-milestone/<id>`（**per-milestone assignee + target_date**）
  - 結案 `POST /audit-round/<id>/close-round`（POA&M 全 closed 才可）
- **驗收**：三層 CRUD / per-里程碑指派 / 180 天告警 / close-round 連動。

---

## 2. 漣漪 / 共用改動 checklist

- [ ] `api.js` 新端點常數（Step 0）
- [ ] 路由 round-scoped（D1）+ menu.json + breadcrumb parent + 側欄高亮 `ui_routes`
- [ ] 按鈕可用性改 round.status 七態（取代 flow stage）
- [ ] RoundSwitcherBar 改接 audit-rounds
- [ ] AuditVerdictPanel 重構成 AO 層 + 新增 RiskPanel
- [ ] i18n：七態 status / round_type / risk severity / milestone 詞彙（en + zh-tw）
- [ ] 舊 view 拔入口（D2）；全綠後刪舊 route + service（另開收尾 task）

## 3. 保留不動（驗證即可）

My Jobs（`MyTasksView`，任務引擎獨立）、Task Setup（`TaskSetupView`，控制項→AO→job 階層，驗 context 傳遞）、JobExecutionDrawer、共用元件庫（StatusBadge / AuditTreeNav / AuditControlRef / FlowPhaseBanner）。

## 4. 開工順序

Step 0 → 1 → 2 → 3 → 4（依賴遞增、風險遞增）。每 Step 獨立 commit + 手測 + 不破壞既有；Step 1 一通整條生命週期入口就活。BE 新引擎 API 已上線，FE 可直接接。

> 對應後端設計：engagement 模型 / 七態狀態機 / 四 clone-snapshot 邊界見
> [`design.md`](design.md) §3、[`api-contract.md`](api-contract.md) §3~§8。
