# 換 session Handoff — 資安掃描 arc 後續優化 Runner（2026-07-25）

| 項目 | 內容 |
|------|------|
| **緣由** | 資安掃描主體修正已驗收（見 6d10fdfb），剩「品質債/優化」後續四工作用 runner loop 自動消化。本 session 跑完 20 輪，四工作全部到「修正待驗證」，交棒給下個 session 收尾（等 user 手測 → push → 收官）。 |
| **branch** | BE `main`、FE `main`（**兩 repo 都不切 branch，維持 user 當下 branch**） |
| **接手前必讀** | ① 本檔全部 ② `docs/features/security-scan-2607/runner-loop-log.md`（20 輪逐輪紀錄）③ 四個 Notion case 內文的「已完成修正（白話）」comment |
| **預估時間** | 純收尾（等 user 手測回報 → push）約 0.5h；若 user 要接著做 backlog / jedi 線另計 |
| **狀態** | **四工作全部 = 修正待驗證，全部 commit 未 push。下個 session 不是修 bug，是「等 user 手測結果 → 按指示 push / 補 backlog」** |

---

## 🧭 原始需求 / WHY（置頂）

**這整件事要解決什麼**：2026-07-24 資安掃描（SonarQube + Trivy + Semgrep）主體洞已修完驗收。追查過程順帶盤出**四類「非安全洞」的品質債/優化**，開成 Notion case 排 backlog，交給一個**自動 runner loop**（就是本 session）分批、保守地消化，**不混進資安主流程**：

1. **小件**：FE `preact` direct dep 掛 HIGH CVE-2026-22028，升版即可。
2. **CM-874 FE Sonar 品質債**：SonarQube FE 1065 條，安全面無真實洞（唯一 VULNERABILITY 是 `sessionShare` Math.random 只產 tab id 誤報）；其餘是品質債——2 條 CRITICAL bug + a11y label 缺失大宗 + S2486 靜默吞例外等。
3. **CM-876 富文本編輯器收斂**：FE 同時養三套編輯器（quill EOL 掛 XSS CVE / ckeditor5 掛 MEDIUM CVE + GPL 授權疑慮 / TipTap 乾淨），收斂到單一 TipTap 拔掉前兩者 CVE 面。
4. **CM-873 BE Sonar 品質債**：SonarQube BE 831 條 code smell（Quality Gate 通過、非安全洞），分批消化。

**目標模型**：runner 每輪照各 case 內文的「🔧 Runner 動工指引」段（授權範圍/禁區/分批/驗證/commit 規範）**嚴格保守執行**——只做指引明確授權的，禁區碰都不碰，拿不準一律跳過留 backlog，**不追求 Sonar 歸零**，只求「能安全清的都清完」。每 case 完成定義都是「修正待驗證」等 user 手測，runner **絕不自動標 Done**。

**本棒在大圖的位置**：runner 已跑完 20 輪、四工作全到「修正待驗證」。**下一棒 = 收官**：等 user 手測各 case → 按 user 指示 push（目前全 local）→ 決定要不要接著清 backlog / 動 jedi 線（那條不在 runner 清單）。

---

## §0 接手讀序（按序讀，附冷接自檢）

🔒 **硬 gate：先懂需求再碰任何 code / push**
1. 本檔「🧭 原始需求 / WHY」+ 本節 —— 搞懂「這是 runner 收尾不是修 bug」
2. `docs/features/security-scan-2607/runner-loop-log.md` —— 20 輪逐輪紀錄（每輪：規則/目錄/條數/commit hash/跳過項），是本 arc 的完整帳本
3. 四個 Notion case（見 §5 座標）內文各自的「## ✅ 已完成修正（白話說明）」comment —— 每 case 做了什麼、跳過什麼、待 user 手測什麼

gate 後才進 §6 pre-flight。

**冷接自檢 4 問（答不出回去讀，別碰 code / 別 push）**：
1. 這四工作現在是什麼狀態？（答：全部「修正待驗證」，全部 commit 未 push）
2. 為什麼 runner 沒把它們標 Done？（答：完成定義是等 user 手測；runner 保守不自動關）
3. 下個 session 該做什麼、不該做什麼？（答：該—等 user 手測結果按指示 push / 補 backlog；不該—自作主張 push、自動標 Done、動禁區/jedi 線）
4. 為什麼一堆條目被「跳過」而不是修？（答：BE 無測試網 + 保守原則，設計意圖註解/介面綁定參數/需改邏輯者一律留 backlog，見各 case 白話說明）

---

## §1 現況（四工作逐一）

### ① preact 升版 ✅
- FE `package.json`：`preact ^10.24.3` → `^10.29.7`（npm 解析至 10.29.7 ≥ 修復門檻 10.28.2，HIGH CVE-2026-22028 direct dep）
- `build:DEV` 過。FE commit `2df15a1`（單獨一 commit）。

### ② CM-874 FE Sonar 品質債 — 🔵 修正待驗證
- **2 CRITICAL bug**（`95fd44c`）：`ComplianceFrameworkVersionManage.vue` 兩 Dialog 版本輸入框 `id="key"` 重複 → `id="version"`（兼修 label 關聯 + focus-on-error）；`AppMenuItem.vue:42` `handleRouteChange(route.path)` → `handleRouteChange()`（多餘引數，no-op，**未動側邊選單高亮機制**）
- **a11y ~215 條全清**（9 批 commit `9967c77`→`dfcb10b` + iframe `98fe54e`）：S6853 label 未關聯 + InputWithoutLabelCheck + FrameWithoutTitle；label 補 `for`、控制項補 `id`（PrimeVue Dropdown/Calendar/MultiSelect/InputSwitch 用 `inputId`）、Slider/SelectButton 用 `aria-labelledby`、隱藏 file input + inline editor 用 `aria-label`、v-for 內動態綁定 id 防撞號
- **S2486 靜默吞例外 66 補 log**（4 批 `3808220`→`c8d787b`）：空/回退/fail-closed catch 補一行 `console.error` 保留原 axios interceptor 行為、**不加 toast 不改流程**
- **跳過留 backlog（非漏修）**：S6819 9 條（`role=button/checkbox` 掛自訂樣式 widget，改 native 需重構 markup+CSS）、a11y ~13 條（label 標的是唯讀顯示 div/區段標題/Tag 清單群，非單一控制項）、S2486 7 條（localStorage 不可用 / router.resolve 正常控制流的預期 noop）

### ③ CM-876 富文本收斂 TipTap — 🔵 修正待驗證
- **五步全綠**（5 commit `25ab632`/`c08b9e4`/`40987cc`/`fdfc7e1`/`1dd0aba`）：
  1-3. 三表單（BulletinForm / SystemFeedbackForm / CruisingFeedbackForm）內文編輯器 PrimeVue Editor(quill) → 既有 `TipTapEditor.vue`；`v-model` 維持輸出 **HTML string**（DB 存 HTML，輸出端 `v-dompurify-html` 不動）、必填紅框以 `.tiptap-invalid` wrapper 保留、`scrollHeight=320px`、移除 CkEditorToolBar slot
  4. `main.js` 移除 PrimeVue Editor 全域註冊 + 刪 `CkEditorToolBar.vue`（實為 quill toolbar、零 live 使用）+ 清 ProjectSummaryReportForm/History 兩死 import；grep 確認全 repo 無 `<Editor>` 殘留
  5. `npm uninstall quill @ckeditor/ckeditor5-build-classic @ckeditor/ckeditor5-vue ckeditor5`（package.json only，package-lock gitignored）
- 每步 `build:DEV` 過。TipTapEditor 本身**零改動**（專案摘要報告在用，確保零回歸）

### ④ CM-873 BE Sonar 品質債 — 🔵 修正待驗證
- 授權 4 安全桶，禁區 S3776/BLOCKER S3516（FR-038 stub）/regex/裸except/logging + 任何改邏輯者
- **S1481 未用區域變數 ✅ 全清（35 修 7 跳）**（`f4312be0`/`77aad18e`）：純死變數刪、有副作用呼叫保留只刪接收變數、tuple 未用改 `_`、未用例外變數移 `as e`。跳過 `workflow_execution_service`×5 + `oscal_audit_service:132-133`（FR-038 stub）
- **S125 註解碼 ⏸ 整桶跳過（66 條）**：大宗設計意圖/未來用註解替代 + 掃描後行號漂移，無測試網逐條比對純死碼風險高
- **S1192 重複字面值 ✅ 安全結構類清完（2 檔 32 處）**（`0c9d3de4`/`4d6fc3e1`）：`bpmn_topology_validator` 屬性 key 抽 `ATTR_*`、`bpmn_generator` schema URI/exporter/錯誤訊息抽 `_BPMN_*`/`_MSG_*`。剩餘資料/i18n/分類標籤類跳過
- **S1172 未用參數 ⏸ 整桶跳過（83 條）**：全為介面/DI/簽名綁定（curr_user×14 / *_uid / logger / gateways）

---

## §2 前次教訓（本 arc 踩過 / 確立的雷，下個 session 沿用）

1. **BE `.env` 難在 shell 直接 source**：`.env` 內 JSON 值含 `}` → `. ./.env` 會 parse error。**別再試 source**。BE 驗證改用**靜態三重檢查**（見 §6）；要真跑服務煙測得 user 本機環境（R17 曾在有 env 時 login 回 400 佐證 boot 正常）。
2. **Sonar 報告行號會漂移**：掃描後代碼有異動（含本 arc 前輪自己的編輯）→ 報告 line number 多處對不上真實位置。**改行號類（刪行/抽常數）Edit 前務必 Read 拿當前精確內容 + grep 確認範圍**，不可信報告行號直接砍。
3. **BE 無測試網 = 保守優先**：pytest 整包 126 collection errors 是既有環境問題（不修不理）；驗證只靠煙測 + 靜態檢查。任何跨 caller / 介面對齊 / 需改邏輯的一律跳過留 backlog，不冒險。
4. **FE package-lock.json 被 gitignore**：`npm install`/`uninstall` 後只 commit `package.json`，別 add lock。
5. **同檔多刪會位移**：一檔多處 Edit，改一個後剩下的行號變了——用「改一個後剩下的變唯一」逐步收斂，或夠長獨特上下文逐一 Edit，避免 replace_all 撞到不該動的。

---

## §3 下個 session 該做什麼（明確步驟）

**這不是修 bug，是收官。按此順序：**

1. **跑 §6 pre-flight** 確認兩 repo branch/working tree/未 push 狀態如預期
2. **等 user 手測回報**（§4 是給 user 的手測 checklist）。user 沒回報前**不要 push**
3. **user 手測 pass → 問 user push 規模**（哪些 repo、要不要一起 push 資安主體那批），得明示才 push。**push 永遠等 user 明確指示**
4. **user 手測發現問題** → 按問題對應 case 修（各 case 白話說明有列改動範圍與檔案），修完重新煙測 + 更新該 case
5. **收官後可選**：問 user 要不要接著清 backlog（見 §7）或動 jedi 線（見 §7，**不在 runner 清單，需 user 明示才走 jedi-package-dev skill**）

---

## §4 給 user 的手測 checklist（各 case 待驗）

**CM-874 FE Sonar**：
- 框架版本管理：新增/編輯版本 Dialog → 版本欄可輸入、必填驗證觸發時焦點正確跳該欄
- 側邊選單：各層級點擊導頁正常、當前頁高亮正常（AppMenuItem 改動區）
- 表單頁抽測（SSP 基本資訊 / 專案建立 / 稽核 AP 編輯 / 問卷設計器 / 各匯入 Dialog）：輸入/下拉/日期/多選/儲存如常
- console：先前靜默失敗的操作現在會印 `[模組] xxx failed` log（畫面行為不變）

**CM-876 TipTap**（重點=相容性）：
1. 開一則**既有公告/回饋**（quill 產的舊 HTML）→ 進 TipTap 編輯 → 粗體/清單/連結 render 不爆版 → 再存 → 輸出仍合法 HTML
2. 四處複測：公告發佈/編輯、系統回饋送出、巡檢回饋送出、專案摘要報告（TipTap 共用無回歸）
3. 必填留空按儲存 → 紅框 + 錯誤訊息
- 驗不過（舊 HTML 爆版）→ 回報，不硬轉

**CM-873 BE Sonar**：
- 本機載 `.env` 起 `python main_app.py`（port 8000）→ login POST 空 body 回 400 + `tail log/app.log` 無 Traceback
- 回歸抽測動到的模組：公告/回饋 CRUD、匯入流程（module_frame/AP/AR docx）、稽核輪次、問卷、BPMN 產生/校驗（bpmn_generator / bpmn_topology_validator）

---

## §5 Notion case 座標 + commit 對照

| Case | Notion page id | 狀態 | 主要 commits |
|------|----------------|------|--------------|
| ① preact | （無 case，小件） | ✅ | FE `2df15a1` |
| ② CM-874 FE Sonar | `3a7346da-4cd0-81ab-87d6-eeb43735e487` | 修正待驗證 | FE `95fd44c` + a11y 9 批 + `98fe54e` + S2486 4 批 |
| ③ CM-876 TipTap | `3a7346da-4cd0-81c8-af28-d2f115bda773` | 修正待驗證 | FE `25ab632`/`c08b9e4`/`40987cc`/`fdfc7e1`/`1dd0aba` |
| ④ CM-873 BE Sonar | `3a7346da-4cd0-81f3-b551-d567d1d7dec5` | 修正待驗證 | BE `f4312be0`/`77aad18e`/`0c9d3de4`/`4d6fc3e1` |

各 case 內文均有「## ✅ 已完成修正（白話說明）」comment（做了什麼/跳過什麼/待手測什麼），作業人員=小弟。

---

## §6 Pre-flight Command（必跑）

```bash
# BE
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
git branch --show-current              # 應 main（不切 branch）
git status --short                     # 我的 commit 都已進版；只剩 pre-existing untracked（docx/png 等）
git rev-list --count origin/main..HEAD # 應 ~34（全未 push）

# FE
cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe
git branch --show-current              # 應 main
git status --short                     # 應乾淨
git rev-list --count origin/main..HEAD # 應 ~27（全未 push）

# BE 靜態驗證法（.env 難 source，改用這組——這是本 case 認可的驗證）
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
python -m py_compile <改過的檔...>                                  # 要 OK
python -m pyflakes  <改過的檔...> 2>&1 | grep -i 'undefined name'   # 要空
# 若 user 本機 env 齊：載 .env 起 python main_app.py，curl -s -o /dev/null -w "%{http_code}" \
#   -X POST localhost:8000/api/1.0/login -H 'Content-Type: application/json' -d '{}' 應 400
```

---

## §7 不在本期 scope（別順手做）

- **jedi-* 線**：HEAD commit `969983f0` 提到「新發現 jedi-issue wheel 憑證外洩 P1 + 開 4 條 Notion case」+ jedi 發版 4 CVE 歸零——**這條不在 runner 四工作清單內**，照 handoff 規範要 **user 明示才動**，走 `jedi-package-dev` skill。runner 沒碰。
- **CI/CD case**：user 指示擱置，Notion 維持原狀，runner 沒碰。
- **各 case 跳過的 backlog**（要清需 user 決策 / 主 session 人工判斷，不是 runner 自動能安全做的）：
  - CM-874：S6819（9，自訂 widget 需重構 markup+CSS）、a11y 唯讀/區段標題 label（~13）
  - CM-873：S125（66，建議重跑 Sonar 拿新行號 + 人工逐檔判斷）、S1172（83，介面/DI 綁定）、S1192 資料/i18n/分類標籤類、S3776 認知複雜度 207（本就禁區）、BLOCKER S3516 7（FR-038 stub 等 2B 重建）
- **push**：全 local，**等 user 明確指示才 push**，別自作主張。

---

## §8 行為規範重要提醒（本收尾適用）

- **不切 branch / 不自動 push**：兩 repo 都在 `main`，push 永遠等 user 明示
- **BE、FE 分開 commit**，顯式 `git add 檔名`（禁 `-A`/`-am`）；FE `package-lock.json` gitignored 不 add
- **改 BE service/route 後要煙測 + 提醒重啟**（BE 重啟 2026-07-22 起由 Claude 負責）
- **收尾等 user 下令**：user 手測 pass 前不標 Done、不 push；「修正待驗證」是等 user verify 的正確狀態
- **憑證不寫入任何 commit 檔**
- **Notion 作業人員**：Claude 做的填「小弟」

---

## §9 前次 session（本 runner）commits 清單

**FE repo（compliance-manager-fe，`origin/main..HEAD` 共 27，本 runner 貢獻 21）— 全未 push**
```
1dd0aba chore(deps): 拔除 quill + ckeditor5
fdfc7e1 refactor(editor): 移除 PrimeVue Editor 全域註冊 + 刪 CkEditorToolBar
40987cc refactor(editor): 巡檢回饋表單 quill 換 TipTap
c08b9e4 refactor(editor): 系統回饋表單 quill 換 TipTap
25ab632 refactor(editor): 公告表單 quill 換 TipTap
c8d787b fix(sonar): S2486 批次 4 收尾（11 檔 11）
0b4d128 fix(sonar): S2486 批次 3（12 檔 27）
babd000 fix(sonar): S2486 批次 2（4 檔 15）
3808220 fix(sonar): S2486 CLI/FrameworkImport（2 檔 13）
98fe54e chore(sonar): a11y iframe title（3 檔 3）
dfcb10b / 0b17245 / 2cbc1b4 / 3c4a0ed / 7155458 / eaa1c7a / 378a143 / c6c0734 / 9967c77  chore(sonar): a11y 9 批
2df15a1 chore(security): preact 升 10.29.7
```

**BE repo（compliance-manager-be，`origin/main..HEAD` 共 34）— 全未 push**
```
969983f0 docs(security-scan): 半夜三工具重掃 MEDIUM 分析（★非 runner，jedi 線相關，見 §7）
547471d6 docs: runner loop log R20（+ 收官）
4d6fc3e1 chore(sonar): S1192 bpmn_generator（4 字面值 19 處）
0c9d3de4 chore(sonar): S1192 bpmn_topology_validator（3 字面值 13 處）
77aad18e chore(sonar): S1481 api/common/core/domain/scripts（19 條 14 檔）
f4312be0 chore(sonar): S1481 app（16 條 9 檔）
+ runner loop log R1~R20 docs commits（每輪一支）
```
其餘 BE commit（`969983f0` 之前更早的 `9fb4a111`/`15d19e3a`... 資安主體升版）是**本 arc 之前**的資安主體修正，已驗收，非 runner 產出。

---

## §10 給 fresh session 的超短 prompt

```
資安掃描 arc 後續優化的 runner 已跑完（4 工作全「修正待驗證」，全 commit 未 push）。
請先讀 docs/features/security-scan-2607/handoff/2026-07-25-security-optimization-runner-session-handoff.md
全部（先懂 WHY：這是 runner 收尾不是修 bug）+ 答冷接自檢 4 問，再跑 §6 pre-flight。
接手任務＝等 user 手測各 case（§4 checklist）→ 按 user 明示 push（目前全 local）；
user 沒下令前不 push、不標 Done、不碰 §7 禁區/jedi 線。手測若發現問題再對應修。
```

---

## §11 附：runner loop log 位置

完整 20 輪帳本：`docs/features/security-scan-2607/runner-loop-log.md`（每輪：時間/作業 case/批次內容/commit hash/跳過項）。此檔是本 arc 唯一「逐輪原始紀錄」，本 handoff 是其收口摘要。
