---
title: FR-119 裁決稿——資安掃描收口十九件待裁（總表 §7 第 36～49 項＋主專案盤點第 50～54 項）
---

# 資安掃描收口：十九件等你裁的事

> 整理卡 CM-2146（母卡 CM-2139）｜整理日期 2026-09-24｜來源：總表 `docs/features/security-scan-consolidated/README.md` §7 第 36～49 項與各項出處的掃描報告；第 50～54 項出自主專案未掃盤點 `scan-inventory.md` 第 7 節。
> 這份文件**只整理、不裁決**：每件的選項與建議都照報告原文，報告沒寫的選項沒有另外補。

## 這份文件怎麼用

1. 先看下面的**總覽表**，十九件一行一件（第 36～49 項是套件掃描帶出的；第 50～54 項是「主專案還剩哪些沒掃」盤點帶出的，決定下一階段掃描的範圍），知道每件在講什麼、首腦或掃描人員建議選哪條。
2. 需要細節時看正文，每件一段，固定七個欄位：標題、場景、現在程式怎麼做、為什麼要你裁、可以選的路、建議、裁完接哪裡。
3. 裁完在最後的**「決策者裁定」表**填「選 A」「選 B」或寫備註，就收工。FR-119 的「打包」那一步會依這張表交給修正線；第 50～54 項則交給下階段主專案掃描開卡。

幾個反覆出現的詞先講清楚：

- **守門**：程式裡檢查「你有沒有資格做這件事」的那一段，例如「你是不是這個專案的成員」。
- **網址（入口）**：前端或任何人可以直接呼叫的後端功能位址。沒有畫面在叫，不代表網址不能打。
- **套件**：我們自己的共用程式庫（jedi-* 系列），主專案引用它。**改套件要發新版**，才會進主專案。
- **修正分支**：放「已寫好、還沒合回主線」修法的分支（`fix/security-b1`），修正卡 CM-2037 的修法在這裡。
- **死碼**：寫了但整個系統沒有任何地方呼叫的程式。
- **凍結快照**：開始稽核時把當下的 SSP（系統安全計畫，專案的主文件）複製一份鎖起來，當稽核證據。
- **資料庫隔離**：資料庫層自動把別家客戶的資料藏起來的機制；查別家客戶的資料會得到「找不到」。
- **出貨基線**：新客戶安裝時拿到的那份資料庫結構。本批十九件都沒有動資料庫結構，**都不需要重產出貨基線**。
- **U 系列（U1～U13）**：盤點把主專案還沒掃過的程式切成的一棒一棒掃描工作，每棒上限 2,000 行、30 支檔。第 50～54 項裁的是這些棒要涵蓋什麼。
- **組裝檔（DI）**：把各個程式零件接在一起的設定檔。零件少接一個，守門程式寫得再好也不會執行，而且不會報錯。

## 十九件總覽

| 項次 | 一句話 | 建議 | 裁完接哪裡 |
|---|---|---|---|
| 第 36 項 | 任務設定樹、目前 SSP 兩支沒人在用的網址，補守門還是拆掉 | **首腦：拆網址**（runner 同） | 總表第 166／167 項同一張卡；改套件要發版 |
| 第 37 項 | 稽核人員寫的改善建議，專案經理能不能改 | 報告**沒給建議** | 決定第 168 項修法是「擋掉」還是「另存」 |
| 第 38 項 | 修正分支守門「沒傳呼叫者就不檢查」要不要改必填 | **runner 與首腦：改必填** | 修正分支順手改，FR-114 合回前；套件要發版 |
| 第 39 項 | 回退標記三支讀取方法是死碼，清掉還是先問產品 | 報告**沒給建議** | 清 → 死碼清理 FR-092；問產品 → 可能開功能卡 |
| 第 40 項 | 複製 SSP 內部參照沒換新編號，修不修、舊快照補不補 | 報告**沒給三選一建議**（V3 runner 建議第 37 項同卡、修在套件） | 非資安第 36、37 項同一張卡；改套件要發版 |
| 第 41 項 | 凍結保護只有主專案一層，套件要不要再加一道 | 報告**沒給建議** | 改套件要發版 |
| 第 42 項 | CM-2037 團隊名單修法擋不住跨客戶，要不要退回 | **首腦：直接退，改成查不到回 404** | 退回修正卡 CM-2037；主專案改，不用發版 |
| 第 43 項 | 稽核中要重排計畫，是否一律走「退回規劃階段」 | runner 傾向「一律走退回」 | 決定第 170 項修不修；runner 建議併 CM-2037 同批 |
| 第 44 項 | 「更新稽核計畫」網址零守門但背後是空殼，拆還是補 | **首腦：拆網址**（runner 同） | 主專案改，不用發版 |
| 第 45 項 | 套件補 `defusedxml`、拿掉 `pyyaml`，是否跟第 171／172 項同次發版 | **runner：同一次發** | jedi-oscal-v2 發版時機 |
| 第 46 項 | 第 133 項修法換查法後，另兩道「從沒擋過」的檢查要不要同卡換 | 報告**沒給建議** | 第 133 項同一張卡（或不動） |
| 第 47 項 | 「捨棄解析工作單」要不要收緊到稽核員或管理者 | 報告**沒給建議**（標可選） | 一行修法，在套件；要發版 |
| 第 48 項 | DEV `blsadmin`（子公司帳號）帶超級管理員旗標是不是刻意的 | runner 判斷「應該是測試資料」 | 是 → 記一筆；不是 → 另開盤點卡 |
| 第 49 項 | 查「工作流程屬於哪個控制項」的輪次編號要不要改必填 | **runner：改必填** | 一行修法，在套件；要發版 |
| 第 50 項 | 「任務入口與批次」（U7）要不要掃 | **盤點員：掃** | 下階段 U 系列開卡範圍（U7） |
| 第 51 項 | 總表「權限共用層已經掃過」那句要更正 | 事實更正，盤點員建議總表補一句 | 總表 §0.5 補一句；下階段 U 系列（U1 排第一） |
| 第 52 項 | 系統設定守門那支掃後又新增 391 行，要不要補掃 | **盤點員：補，併 U12** | 下階段 U 系列開卡範圍（U12 或單獨一棒） |
| 第 53 項 | 組裝檔專掃用掃描工具還是用腳本 | 盤點員：全部對照不要用工具、用腳本 | 下階段 U 系列開卡範圍（U13），或改開實作卡 |
| 第 54 項 | 「人員對帳跨公司比對」沒查完，要不要補 | 盤點員**沒說要不要補**；要補就併 U12 | 下階段 U 系列開卡範圍（U12） |

**互相牽連的幾組**（裁的時候一起看）：

- **第 36 項與第 44 項**：同一種處理（沒人在用的網址，拆或補），首腦兩件都明示拆。
- **第 38、42、43 項**：都跟修正卡 CM-2037 有關（38 是它的寫法、42 是它的漏洞、43 的修法 runner 建議併進它那一批）。
- **第 40 項**已經把非資安第 37 項（專案 SSP 再匯入 uuid 換新）併進來，一起裁。
- **第 46 項**綁著總表第 133 項的修法；**第 37 項**綁著第 168 項；**第 43 項**綁著第 170 項；**第 45 項**綁著第 171／172 項。
- **第 52 項與第 54 項**都要併進 U12：兩件都併，U12 約 1,770 行，仍在一棒 2,000 行上限內。
- **第 50～54 項**裁完都只決定下階段主專案掃描（U 系列）的開卡範圍，不產生修正卡、不發版。
- **改套件就要發版**的：jedi-compliance-audit 有第 36、38、47、49 項（第 37 項也牽到它）；jedi-oscal-v2 有第 40、41、45 項。發版時機要不要合併，報告只有第 45 項講到。

---

## 第 36 項：任務設定樹、「目前 SSP」兩支沒人在用的網址，補守門還是拆掉

- **場景**：同一家客戶的一般員工小王只參與專案甲。他知道了專案乙的編號，直接打「任務設定樹」網址，拿到專案乙納入稽核的控制項清單、每個目標的收證據任務數，還有**每位被指派人的姓名**；打「目前 SSP」網址，拿到專案乙主文件的編號與狀態。正常畫面上專案乙是擋他的，這兩條網址不擋。別家客戶的編號打不到（資料庫隔離擋住）。
- **現在程式怎麼做**：兩支都只查「有沒有登入」和「客戶有沒有買專案模組」，不查是不是專案成員。前端已沒有畫面在叫（任務設定頁在 FR-114 已裁拆除；「目前 SSP」前端只剩一個沒人呼叫的方法），但後端網址還掛著。位置：套件 `api/routing.py:31-35`。
- **為什麼要你裁**：這是「入口留不留」的修法方向二選一，不是技術問題。
- **可以選的路**：
  - **A. 補守門**：兩支開頭加「是不是專案成員」檢查，任務設定樹再比對「後面那個編號解出的專案＝網址上的專案」。代價：多維護兩個沒人用的入口。
  - **B. 拆網址**：兩支網址從套件拿掉，問題連同入口一起消失。代價：要先派人確認沒有其他消費者（例如 AI 儀表板或外部整合），掃描那一棒沒做這一步。
- **建議**：**首腦明示選 B 拆網址**。runner 建議同樣是 B，理由：「沒人用的網址，守門補得再好也是多一個要維護的入口。」
- **裁完接哪裡**：總表第 166、167 項同一張修正卡。選 B 要先加一步「確認沒有其他消費者」。網址在 jedi-compliance-audit 套件，要發版。不需重產出貨基線。

## 第 37 項：稽核人員寫的「改善建議」，專案經理能不能改

- **場景**：輪次進入「整改中」後，稽核人員在每個風險底下留一筆「改善建議」，系統規定這筆不能刪。專案經理（受稽核的一方）拿到這筆建議的編號，用「新增整改計畫」送出同一個編號、把類型改成一般整改計畫，系統當成「更新既有那筆」，稽核人員寫的內容就被改掉；接著再按刪除，「建議不可刪」的檢查已經不成立，整筆刪掉，也不留原文。
- **現在程式怎麼做**：送進來的編號與類型都是自由字串、沒限制值域，底下「編號對得上就覆蓋」；刪除保護只看「現在的類型是不是建議」。位置：主專案 `audit_round_route.py:440`（新增整改計畫的入口）。
- **為什麼要你裁**：這是產品規則——稽核建議屬於誰。三位檢查員 2:1，反對那票認為「經理本來就有權改整改計畫」，另兩票認為稽核建議屬稽核方的紀錄。裁完才知道修法是「擋掉」還是「另存」。
- **可以選的路**：
  - **A. 稽核方專屬，受稽核方完全不能動**：新增整改計畫時拒絕覆蓋類型是「建議」的那筆，刪除也擋。最單純，稽核獨立性最完整。
  - **B. 經理可以改，但要留痕**：經理的修改另存一筆、原建議保留不動，稽核人員看得到誰改了什麼。保留彈性，代價是修法多一層資料結構。
- **建議**：報告**沒給建議**（只建議登記成新項次，已登記為總表第 168 項）。
- **裁完接哪裡**：決定第 168 項的修法。報告提醒這段服務也屬 FR-116 C3 那一棒的範圍，併卡時要去重。修法兩側都有（主專案＋jedi-compliance-audit 套件），動到套件就要發版。選 B 需要新的資料結構，報告沒規劃細節。

## 第 38 項：修正分支的守門「沒傳呼叫者就不檢查」，要不要改成必填

- **場景**：修正卡 CM-2037 在稽核流程套件裡補了「讀取稽核輪次要是專案成員」的檢查，但寫成「有傳使用者才檢查、沒傳就放行」。現在主專案那邊還沒改成傳使用者（修正版的主專案路由也還在修正分支沒合回），所以開發機上**這道檢查一次都不會觸發**，手測時容易以為修好了。更大的問題是：以後任何一個新呼叫端忘了傳，會安靜放行、不報錯。
- **現在程式怎麼做**：修正分支上的套件寫法是 `list_rounds(project_uid, curr_user_id=None)`，裡面「有傳才檢查」。
- **為什麼要你裁**：這是修法寫法的方向二選一，而且牽涉 FR-114 合回的時機。
- **可以選的路**：
  - **A. 改成必填**：漏傳直接報錯，下一個呼叫端不可能忘。範圍只有修正分支那幾支方法與呼叫端，可以在 FR-114 合回前順手改。
  - **B. 維持選填**：不動修正分支，靠每個新呼叫端自己記得傳；漏了不會有任何訊號。
- **建議**：**runner 與首腦都建議 A 改成必填**。
- **裁完接哪裡**：修正分支 `fix/security-b1`，FR-114 合回前改；報告也寫「或另開一張小卡」。改的是 jedi-compliance-audit 套件，要隨修正分支一起發版。報告另附一件（不在本項裁決範圍、只提醒）：修正分支合回之前，開發機手測「輪次讀取守門」會得到錯的結論。

## 第 39 項：回退標記的三支「讀」的方法沒人在用，清掉還是先問產品

- **場景**：稽核輪次被退回時，系統會把已產生的 SSP、稽核計畫、改善計畫標成「作廢」存起來（DEV 目前 13 筆，階段歷程 48 筆）。可是負責讀這份標記的三支方法，整個系統沒有任何地方呼叫——**只記作廢、從不讀作廢**，所以退回後被作廢的東西，在列表上看不出來。
- **現在程式怎麼做**：`RoundRollbackSupersessionDomainService` 的 `is_superseded`、`list_by_entity_ids`、`list_by_round` 三支零呼叫；系統只用到它的「新增」。
- **為什麼要你裁**：這不是資安問題，是要先決定它是「沒用的程式」還是「漏做的功能」。
- **可以選的路**：
  - **A. 列進死碼清單**：交給 FR-092 一起清掉三支讀取方法，標記照記不動。前提是產品確認本來就不打算在畫面上顯示作廢。
  - **B. 先問產品**：問「退回後被作廢的 SSP／稽核計畫／改善計畫，列表上本來要不要標出來」。如果本來要做而漏掉了，這是功能缺口，要開功能卡補畫面，不是清死碼。
- **建議**：報告**沒給建議**，兩條並列。
- **裁完接哪裡**：選 A → 併 FR-092 死碼清理。選 B → 產品回覆後，要做就開功能卡（不歸資安修正線）。不需重產出貨基線。

## 第 40 項：複製 SSP 時內部參照沒換新編號，要不要修；已經指錯的凍結快照要不要修補

- **場景**：開專案時從資源庫範本複製 SSP、開始稽核時再複製一份凍結快照，走的是同一支複製程式。每複製一次，有三種欄位還指著來源 SSP：沿用授權的「提供者」、元件上的「沿用授權編號」、資產清單上的「元件編號」。DEV 凍結快照裡 **47 筆提供者全部指錯**（草稿 SSP 裡也有 515 筆）。畫面顯示時只會變空白、不會帶出別份 SSP 的內容，也沒有程式拿它去全表找人，所以**不會跨份讀到別人的資料**；但稽核證據裡這一欄對不上任何人。
  - **同族一起裁（非資安第 37 項）**：專案負責人在「專案 SSP」頁把同一份 Word 或 Excel 再匯入一次時，人員、實作項目等每次換新編號，外部服務與設備每次多一份。DEV 有 17 筆外部服務的提供者查無此人（混著本項的效果）。這條 DEV 無法直接重現，是讀程式碼推論。
- **現在程式怎麼做**：複製人員時產生了「舊編號→新編號」對照表，但沒傳給 SSP 複製，所以這三種欄位原樣照抄。位置：套件 `ssp_clone_service.py:170-176`。
- **為什麼要你裁**：修程式沒有爭議，爭議在「已經凍結的稽核證據要不要改」——這是稽核證據的處置規則，不是技術問題。
- **可以選的路**：
  - **A. 開卡修程式，舊快照不動**：往後複製的都對，已凍結的維持原樣。稽核證據一個字都不動，代價是舊快照裡這欄一直是錯的。
  - **B. 開卡修程式，也修補舊快照**：用對照關係把舊快照的編號改正。**修補本身就是改動稽核證據**，要另外決定誰核准、要不要留紀錄（改了哪幾筆、改前改後）。
  - **C. 先不開卡**：記著不動，等有畫面或報表真的要用這欄時再修。
- **建議**：報告**沒給 A／B／C 的建議**。V3 runner 建議把再匯入那條（非資安第 37 項）跟本項開**同一張卡**，修法都落在套件；那條要修的人先用一份 Word 在 DEV 跑兩次確認。
- **裁完接哪裡**：總表 §3.2 非資安第 36、37 項同一張卡。修法在 jedi-oscal-v2 套件，要發版。選 B 另要一份資料修補做法（報告沒規劃）；本項不動資料庫結構，不需重產出貨基線。

## 第 41 項：凍結保護只有主專案一層，套件要不要再加一道

- **場景**：稽核開始後 SSP 會凍結成快照當證據。今天從畫面上改不動它——主專案每一條寫入 SSP 的網址都會先檢查「這份是不是凍結快照」，是就拒絕（這點掃描已確認，不是洞）。但套件自己的寫入方法完全不看狀態。將來如果有新的呼叫端（新套件、背景工作）直接叫套件、沒經過主專案那道檢查，就能改動稽核證據，而且不會報錯。
- **現在程式怎麼做**：套件凍結時只把狀態設成「已凍結」（`oscal_snapshot_service.py:87`），套件的 `ssp_service.update_*` 一支都不看這個狀態；保護全在主專案的 `SspPermissionChecker`。
- **為什麼要你裁**：這是「要不要多一層保險」的方向決定，現在沒有被打穿。
- **可以選的路**：
  - **A. 套件層加第二道**：`ssp_service` 的寫入方法遇到「已凍結」就拒絕。新呼叫端忘了也擋得住；要先確認沒有合法流程需要寫入已凍結的 SSP（例如凍結當下那一步）。
  - **B. 維持主專案一層**：不動套件，靠每個新呼叫端都記得走主專案的檢查；漏了不會有任何訊號。
- **建議**：報告**沒給建議**。
- **裁完接哪裡**：選 A → 修在 jedi-oscal-v2 套件，要發版；報告沒指定併哪張卡。選 B → 不動。不需重產出貨基線。

## 第 42 項：CM-2037 對「稽核團隊名單」的修法擋不住跨客戶，要不要退回重修

- **場景**：別家客戶的人拿到我們某份稽核計畫的編號，打「稽核團隊名單」網址，可以拿到團隊成員的姓名、Email、電話。修正卡 CM-2037 補了檢查，但寫成「查得到這份計畫的輪次，才檢查你是不是專案成員」——而別家客戶的輪次會被資料庫隔離藏起來、查回來是「找不到」，於是檢查整段略過，名單照樣吐出去。等於**擋住了同客戶跨專案，沒擋住跨客戶**，而跨客戶正是最嚴重的那一面。
- **現在程式怎麼做**：修正分支 `assessment_plan_app_service.py:718-722`：「有找到輪次才檢查」。首腦已開修正分支這幾行核實。同一支檔另一個檢查（`resolve_ap_and_check_participant`）的寫法是「找不到就回 404（找不到的錯誤）」，這支沒照做。
- **為什麼要你裁**：退回一張已完成的修正卡，要決策者點頭。
- **可以選的路**：
  - **A. 退回 CM-2037，改成「查不到輪次就回 404」**：跟同檔另一支守門同寫法，改動只有幾行，不必等其他待裁。
  - 報告只給這一條路；不點頭就是維持修正分支現在的寫法。
- **建議**：**首腦明示選 A 直接退**。V8 runner 同樣建議改成查不到就 404。
- **裁完接哪裡**：退回修正卡 CM-2037（修正分支 `fix/security-b1`）。改的是主專案，不用發套件版。不需重產出貨基線。

## 第 43 項：稽核中發現計畫要重排，是不是一律走「退回規劃階段」的正式流程

- **場景**：某輪稽核已進入「稽核中」，稽核員照計畫填完一半判定。這時稽核員或管理者按「重新產生草稿」，輪次就改指向一份**新的空白計畫**；原計畫還在資料庫但跟輪次脫鉤、不留理由，之後任何人打開這一輪看到的都是空白計畫。已結案的輪次也一樣能按。
- **現在程式怎麼做**：「改稽核計畫」有五個入口，四個都有「只限規劃階段」那一行，「重生草稿」自己查了角色、漏了階段那一行。位置：主專案 `assessment_plan_app_service.py:662-683`。
- **為什麼要你裁**：這是產品規則——稽核中有沒有「重排計畫」的正當需求。沒有，就一行修掉；有，就要另外設計留痕。
- **可以選的路**：
  - **A. 一律走退回規劃階段**：重生草稿跟其他四個入口一樣，只限規劃階段；要重排就先走退回流程（有紀錄、有理由）。修法一行。
  - **B. 稽核中允許重生**：要另外設計留痕（誰在什麼階段重生、原計畫怎麼保存），修法比較大，第 170 項暫不修。
- **建議**：V8 runner 傾向 A（報告寫「如果有正當需求，應該走退回規劃階段那條正式流程，而不是直接重生」），並建議這條登為低、併 CM-2037 同一批修（同一支檔、一行修法）。
- **裁完接哪裡**：決定總表第 170 項修不修。選 A → runner 建議併 CM-2037 同批。改的是主專案，不用發版。不需重產出貨基線。

## 第 44 項：「更新稽核計畫」那條網址要拆掉，還是先補守門

- **場景**：現在沒人會受害，但它是一顆地雷。「更新稽核計畫」這條網址只查登入和商務授權，網址上的專案編號收下後完全沒用；背後的服務是早年換資料模型時關掉的空殼，收到什麼都回「沒有東西」、不寫資料庫（前端若真的叫了，會以為改成功）。前端有定義這支，但全前端沒有任何地方呼叫。**哪天有人把服務重建起來、忘了補守門，就會變成「同一家客戶任何人都能改別人專案的稽核計畫」。**
- **現在程式怎麼做**：網址 `assessment_plan_route.py:55-58` 只掛登入與授權；服務 `project_service.py:534` 本體只有一行 `return None, False`。
- **為什麼要你裁**：跟第 36 項同一種「入口留不留」的方向二選一。
- **可以選的路**：
  - **A. 拆掉網址**：沒人叫、服務是空殼，直接拿掉，入口跟地雷一起消失。
  - **B. 補守門、保留空殼**：先掛「改專案」的能力點與參與者檢查，將來重建時不會漏；代價是多維護一個沒人用的入口。
- **建議**：**首腦明示選 A 拆網址**。runner 建議同樣是 A，理由同第 36 項。
- **裁完接哪裡**：報告沒指定哪張卡；可跟第 36 項同一種處理一起派。改的是主專案，不用發版。不需重產出貨基線。

## 第 45 項：套件補宣告 `defusedxml`、拿掉 `pyyaml`，要不要跟第 171／172 項同一次發版

- **場景**：平台管理員在「框架管理」上傳 CMMC 的 Excel 時，系統靠一個叫 `defusedxml` 的防護元件擋「XML 炸彈」（特製檔案讓解析吃光資源）。主專案有宣告這個元件，所以現在有防護；但 jedi-oscal-v2 套件自己沒宣告，換一個只裝這支套件的環境，防護就靜默消失（這條 Excel 路徑目前也沒有網址入口，現在打不到）。反過來，套件宣告了 `pyyaml` 卻一行都沒用到。
- **現在程式怎麼做**：套件依賴清單缺 `defusedxml`、多一個沒用的 `pyyaml`（套件 `pyproject.toml:15`）。
- **為什麼要你裁**：這是發版時機的決定。兩件本身都很小，但改套件就要發新版；同一支套件裡還有第 171／172 項（CMMC PDF 解析器撐爆記憶體、卡住工作程序）也要修。
- **可以選的路**：
  - **A. 同一次發**：一次發版、一次驗收，省一輪流程。
  - **B. 分開發**：依賴清理不等修正卡，先併進 FR-092 死碼清理那批；代價是多發一次版。
- **建議**：**runner 建議 A 同一次發**。
- **裁完接哪裡**：jedi-oscal-v2 發版。選 A → 跟第 171／172 項同一張修正卡、同一次發；選 B → 併 FR-092。報告另建議順手拿掉兩個沒人用的常數（`ImportType.YAML`／`JSON`）。不需重產出貨基線。

## 第 46 項：第 133 項修法換查法之後，另外兩道「從來沒擋過」的檢查要不要同一張卡一起換

- **場景**：總表第 133 項是「平台管理員刪框架或刪版本時，後端不檢查還有沒有客戶在用」。掃描發現第 133 項目前寫的修法（照編輯路徑那樣呼叫一支「有沒有被引用」檢查）擋不住：那支檢查查的是一個正常流程裡**永遠不會有資料**的連結（DEV 實查 0 筆）。真正記錄「哪些客戶的資源庫用了這個版本」的，是資源庫表上的版本編號欄。問題是：**編輯公版目錄那六支、以及「匯入覆蓋既有版本」那一道**，現在呼叫的也是同一支查錯地方的檢查——從來沒擋過東西，真正在擋的是旁邊「版本必須是草稿」那一道。
- **現在程式怎麼做**：編輯路徑的引用檢查在 `framework_version_edit_service.py:258-266`，查的是基準線是否指向公版目錄；正確該查的是 `module_frames.oscal_framework_version_uid`（要用系統層跨客戶查）。
- **為什麼要你裁**：修正卡的範圍決定——大卡一次修乾淨，還是小卡只修刪除。
- **可以選的路**：
  - **A. 同卡一起換**：刪除、編輯、匯入覆蓋三處都改查同一欄，一次驗收；「已發佈版本不能改」照舊由草稿檢查擋，換掉後多一道真的會擋的。
  - **B. 只修刪除，另兩處不動**：修正卡小；代價是那兩道繼續是裝飾品，下一個人看到會以為有守。
- **建議**：報告**沒給建議**。報告另要求第 133 項本身改寫（修法改成查資源庫上的版本編號；後果改成「公版目錄變孤兒、客戶資源庫的版本連結斷掉」，不是「整份標準憑空消失」），嚴重度要不要因此下修請首腦定——這些是總表改寫，不在本項裁決範圍。
- **裁完接哪裡**：總表第 133 項那張修正卡。改的是主專案，不用發版。報告另問「刪主版本、刪有子版本的版本會吐 500 錯誤」要不要順手記進同卡（非資安）。不需重產出貨基線。

## 第 47 項：「捨棄解析工作單」要不要收緊到稽核員或管理者

- **場景**：稽核員上傳稽核計畫 Word 後，系統存成一張「解析工作單」等人確認。現在專案裡的「檢視者」「觀察者」也能按「捨棄」，把稽核員還沒確認的工作單丟掉。影響只到同一個專案、只是軟刪一張暫存單，重新上傳就回來。
- **現在程式怎麼做**：「捨棄」是寫入動作，守門卻用了讀取的標準（是專案成員就行）；上傳與確認用的是「稽核員或管理者」。位置：套件 `ap_docx_import_app_service.py:172`。
- **為什麼要你裁**：不是資安項次，是產品規則——誰可以丟掉別人上傳到一半的東西。
- **可以選的路**：
  - **A. 收緊**：捨棄跟上傳、確認一樣，只限稽核員或管理者。修法一行（把守門換成 `resolve_ap_and_check_auditor`）。
  - **B. 維持**：專案成員都能丟，接受「別人可能把我上傳到一半的東西丟掉」。
- **建議**：報告**沒給建議**（報告把這件標成「可選」）。
- **裁完接哪裡**：報告沒指定哪張卡。修法在 jedi-compliance-audit 套件，選 A 要發版。不需重產出貨基線。

## 第 48 項：DEV 的 `blsadmin` 帳號（子公司）帶「超級管理員」旗標，是不是刻意的測試資料

- **場景**：DEV 有兩個帳號帶「超級管理員」旗標：總部的 `admin`，以及**子公司 102** 的 `blsadmin`。這個旗標在程式很多地方被當成「平台管理員」（例如解析工作單的公司檢查會對它放行）。整個系統沒有任何畫面或網址能設這個旗標，只能直接改資料庫，所以它應該是測試資料；但如果它是刻意模擬「子公司也能有平台管理員」，那每個讀這個旗標的地方都要重新想一次。
- **現在程式怎麼做**：登入身分組裝時把帳號的超級管理員旗標當成「是管理員」（`jedi-iam/jedi_iam/middleware/context.py:130`）。掃描確認就算子公司帳號帶了它，也繞不過資料庫隔離與專案成員檢查。
- **為什麼要你裁**：只有你知道這筆資料為什麼存在，是事實確認，不是技術問題。
- **可以選的路**：
  - **A. 是測試資料**：記一筆、不用動程式；DEV 要不要把旗標拿掉另說。
  - **B. 產品上允許子公司帳號帶這個旗標**：要另開一張盤點卡，把所有讀這個旗標的地方逐處確認放行範圍對不對。
- **建議**：報告沒給選項建議，但 runner 判斷寫「`blsadmin` 應該是測試資料」（傾向 A）。
- **裁完接哪裡**：選 A → 記一筆，不開卡。選 B → 另開盤點卡（報告沒指定範圍）。不需發版、不需重產出貨基線。

## 第 49 項：查「工作流程屬於哪個控制項」那支方法的輪次編號，要不要改成必填

- **場景**：稽核結果 Excel 匯入、系統自動配對佐證時，會拿控制項代號（例如 `AC.L1-b.1.i`，所有客戶都一樣的字串）去查一張對照表，輪次編號是選填。現在唯一的呼叫端一定帶輪次（輪次找不到會先回 404），不會出事；但那張表沒有客戶欄位、也沒開資料庫隔離，哪天有人新增呼叫端忘了帶，就變成「用所有客戶都一樣的控制項代號查全系統」。就算撈到別家的對照，後果也只是過濾範圍變寬，不是多給佐證。
- **現在程式怎麼做**：套件 `wf_control_mapping_lookup_query.py:30-53` 的 `get_wf_ids_by_control_ids`，輪次編號選填。
- **為什麼要你裁**：跟第 38 項同型——「選填參數漏傳時安靜放行」要不要先堵，現在沒有風險。
- **可以選的路**：
  - **A. 改必填**：改一行，將來漏帶會直接報錯，不會安靜查全系統。
  - **B. 維持**：靠寫新呼叫端的人自己記得帶；現況沒有風險。
- **建議**：**runner 建議 A 改必填**（報告寫「成本是一行」）。
- **裁完接哪裡**：報告沒指定哪張卡。修法在 jedi-compliance-audit 套件，選 A 要發版。不需重產出貨基線。

## 第 50 項：「任務入口與批次」那 7 支要不要掃

- **場景**：專案裡只能看、沒有待辦任務的「檢視者」，可以把別人的稽核任務標成完成（總表第 59 項，單筆完成那條路已查到）。當時有人提到「批次完成」那條路似乎會擋下，但沒核對；而批次完成那支程式裡有一段「預設把呼叫者當管理員」，正是第 59 項沒核對的地方。這支、加上 Excel 批次建任務、「我的任務」與儀表板查詢，共 7 支 1,908 行，從來沒被掃過。
- **現在程式怎麼做**：核對點在 `job_batch_complete_service.py:50-56`。先前 FR-115 盤點把這幾支寫成「屬任務平台地盤、FR-095 裁停所以沒掃」；但 FR-095 那張卡（H2，CM-1783）是「待派」、從來沒派，不是「裁不掃」，而且這幾支在主專案、不在套件。
- **為什麼要你裁**：這是掃描範圍的決定——先前的「裁停」其實沒有人裁過，要你確認一次。
- **可以選的路**：
  - **A. 掃**：排進 U7（7 支 1,908 行，一棒）。順序建議排第 6。
  - **B. 不掃**：維持先前「不在範圍」的處理；第 59 項批次那條路的核對點繼續沒人看。
- **建議**：**盤點員建議 A 掃**，理由是總表第 59 項的核對點在這。
- **裁完接哪裡**：下階段主專案 U 系列掃描的開卡範圍（U7）。不需發版、不需重產出貨基線。

## 第 51 項：總表「權限檢查共用層已經掃過」那句要更正

- **場景**：讀總表的人看到「`common/authz/`（全專案共用的權限檢查那一層）FR-085 C1 已掃」，會以為這層是安全的、排到後面。實際上這一層 12 支檔裡，只有 3 支（專案、SSP、流程三支）被別棒順帶讀過，其餘 9 支沒人讀過，包括 367 行的 `license.py`（授權檔功能開關）與 180 行的決策表。FR-085 C1 掃的是 jedi-common 套件，不是主專案這一層。
- **現在程式怎麼做**：這件不是程式問題，是文件記錯。盤點用掃描紀錄（stamp）逐支比對，9 支零命中。
- **為什麼要你裁**：嚴格說不是裁決、是事實更正；但要寫進總表，而且它讓權限共用層變成下一階段的第一棒，你要知道。
- **可以選的路**：
  - **A. 照盤點更正**：總表 §0.5 補一句「`common/authz/` 只有 3 支被讀過、9 支沒碰」。
  - 盤點只給這一條路；不點頭就是總表維持現在的寫法。
- **建議**：盤點員建議 A，在總表 §0.5 補一句；並建議權限共用層排第一棒（U1）。
- **裁完接哪裡**：總表 §0.5 補一句（回寫時做）；下階段主專案 U 系列掃描的開卡範圍（U1）。不需發版、不需重產出貨基線。

## 第 52 項：系統設定守門那支掃完後又新增 391 行，要不要補掃

- **場景**：平台管理員在系統設定頁改 AI 金鑰、Google Drive 應用程式設定，這兩組只限平台管理員能動——擋這件事的守門，就寫在 `guarded_system_config_service.py`。這支在 09-15 被 FR-096 掃過，之後 09-17～18 又加了 391 行、12 支函式（AI 金鑰遮罩與寫入合併、Google Drive 設定群組、平台管理員守門本身）。新增的量比掃的時候還大，而且新增的就是守門，掃描工具從沒讀過。
- **現在程式怎麼做**：這支現在 665 行。總表第 74 項 09-20 複查時人工看過「這道守門的涵蓋名單只有 AI 金鑰與雲端硬碟兩組」，但沒經過掃描工具。
- **為什麼要你裁**：這是掃描範圍的決定——掃過的檔之後又改大了，要不要重掃。
- **可以選的路**：
  - **A. 補掃，併進 U12**：U12 本來 709 行，加上後約 1,374 行，一棒內。
  - **B. 補掃，單獨一棒**：盤點也列了這條（併 U4 會爆到 2,451 行，所以不併 U4）。
  - **C. 不補**：維持 09-15 那次掃描的結論，新增的守門沒經工具。
- **建議**：**盤點員建議補，放 U12 一起**（A）。同一個模組的 `tenant_storage_config_seeder.py`（掃後新增 47 行）建議跟這支一起帶。
- **裁完接哪裡**：下階段主專案 U 系列掃描的開卡範圍（U12，或單獨一棒）。不需發版、不需重產出貨基線。

## 第 53 項：組裝檔（DI）專掃用掃描工具還是用腳本

- **場景**：某個服務宣告自己需要四個零件（其中一個是守門），組裝檔只接了三個——守門程式寫得再完整也不會執行，而且不會報錯。FR-113 O9b 與 FR-116 C1／C5 已經證實過這種事。這種問題不在任何一支業務程式裡，要逐一對照「宣告要什麼、組裝給了什麼」才看得出來。
- **現在程式怎麼做**：主專案組裝相關檔共 75 支、11,062 行，其中 17 支（2,840 行）從沒碰過，包括身分與權限套件的主專案接線 `core/plugins/identity.py`（679 行）與授權檢查的零件。另外 58 支雖然被掃過，多半是順帶，不是專門對照零件。
- **為什麼要你裁**：這是做法與成本的決定——掃描卡還是實作卡、做 2 棒還是 6～7 棒。
- **可以選的路**：
  - **A. 用掃描工具，只掃沒碰過的 17 支**：超過一棒上限，切兩半（U13a 1,666 行、U13b 996 行），共 2 棒。
  - **B. 用掃描工具，全部 75 支對照一遍**：要切 6～7 棒。
  - **C. 用腳本，全部 75 支對照一遍**：寫一支腳本列出每個服務的建構參數、再列出組裝給的參數，比對缺漏。這是實作卡、不是掃描卡。
- **建議**：盤點員**不建議 B**（工具擅長找「程式寫錯」，不擅長找「少接一條線」），全部對照用 C 腳本比較快，建議首腦裁要不要開這張實作卡。A 與 C 之間盤點員沒給建議。
- **裁完接哪裡**：選 A／B → 下階段主專案 U 系列掃描的開卡範圍（U13）；選 C → 另開一張實作卡，不在掃描線。不需發版、不需重產出貨基線。

## 第 54 項：「人員對帳跨公司比對」沒查完，要不要補

- **場景**：使用者匯入 SSP 的 Word 檔時，系統會把 Word 裡寫的人名對到系統裡的使用者（人員對帳）。會不會對到別家公司的使用者？FR-113 O9b 那一棒點名要查，但三人面板投票 0 票回收，報告自承「人員對帳的跨公司比對」沒查完。
- **現在程式怎麼做**：這部分是 `reconciliation/` 五支加 `party_reconciliation_service.py`，約 400 行，現在算「部分掃過」（工具讀過但面板沒跑完，不能當作掃乾淨）。
- **為什麼要你裁**：這是掃描範圍的決定——沒跑完的那一棒要不要補。
- **可以選的路**：
  - **A. 補，併進 U12**：U12 約 +400 行；若第 52 項也併 U12，合計約 1,770 行，仍在一棒上限內（併 U9 會超過）。
  - 盤點只給這一條路；不點頭就是這幾支維持「部分掃過」。
- **建議**：盤點員**沒說要不要補**，只說若要補，併 U12。
- **裁完接哪裡**：下階段主專案 U 系列掃描的開卡範圍（U12）。不需發版、不需重產出貨基線。

---

## 決策者裁定

> 十九件全部裁定完畢（2026-09-25，決策者逐件裁、首腦每件先給建議與判斷理由）。

| 項次 | 一句話 | 選哪條（A／B／C） | 備註 |
|---|---|---|---|
| 第 36 項 | 任務設定樹、目前 SSP 兩支網址：補守門／拆 | 選 B：拆網址 | 與第 44、43 項同批；套件 api/routing.py 拆兩支、要發版 |
| 第 37 項 | 改善建議：稽核方專屬／經理可改但留痕 | 選 A：稽核方專屬 | 第 168 項修法＝類型是「建議」那筆拒絕覆蓋與刪除；不做另存留痕 |
| 第 38 項 | 修正分支守門參數：改必填／維持選填 | 選 A：改必填 | 修正分支 fix/security-b1 順手改，FR-114 合回前；套件要發版 |
| 第 39 項 | 回退標記讀取：列死碼／先問產品 | 選 B：不清、記功能待補 | 階段回退作廢表已寫、讀的那半沒接；功能上不會抓錯（輪次 ssp_id 決定現用）；記「凍結歷史標記作廢／瀏覽」功能待辦，三支讀取保留 |
| 第 40 項 | 複製 SSP 參照：修程式不補快照／修程式也補快照／先不開卡 | 選 A：修程式、舊快照不動 | §3.2 第 36／37 項同卡修在套件；DEV 47 份凍結快照留著不清不補（凍結證據不事後動）；STG／POC 出貨前視情況再查 |
| 第 41 項 | 凍結保護：套件加第二道／維持一層 | 選 A：套件加第二道 | 凍結是套件自己定義的（snapshot_ssp／FROZEN_STATUS「immutable marker」），套件 update_* 自己擋 frozen；與第 45 項同次發版 |
| 第 42 項 | CM-2037 團隊名單：退回改 404（點頭／不點頭） | 點頭：退回 CM-2037 | list_ap_parties 改「查不到輪次就 404」；主專案改不發版 |
| 第 43 項 | 稽核中重排：一律走退回／允許重生 | 選 B：拆網址 | generate-draft 前端零呼叫、後端只有該路由呼叫、v1.20.0 release note 已點名退役；連同 launch-audit／start-auditing／ar/finalize 三支一起裁；e2e step 同拆；第 170 項隨之消失 |
| 第 44 項 | 更新稽核計畫網址：拆／補守門 | 選 B：拆網址 | 與第 36、43 項同批 |
| 第 45 項 | 套件依賴清理：同次發／分開發 | 選 A：同次發版 | jedi-oscal-v2：第 171／172 項修＋defusedxml 補宣告＋拿 pyyaml／ImportType.YAML,JSON＋第 41 項凍結第二道＋§3.2 第 36／37 項，一次發 |
| 第 46 項 | 另兩道引用檢查：同卡換／只修刪除 | 選 A：三處同卡換 | 刪版本／編輯公版目錄／匯入覆蓋三處改查 module_frames.oscal_framework_version_uid，有任何客戶引用即拒絕；理由是保護稽核依據可追溯（業界慣例已引用版本不硬刪）；第 133 項維持中 |
| 第 47 項 | 捨棄解析工作單：收緊／維持 | 選 A：收緊 | 捨棄解析工作單改稽核員或管理者，與 Excel 側一致；套件一行、同次發版 |
| 第 48 項 | `blsadmin` 旗標：測試資料／產品允許 | 選 A：測試資料 | 首腦唯讀查三環境：DEV admin＋blsadmin(102)、STG 只 admin、POC 只 admin；STG／POC 乾淨，DEV blsadmin 拿不拿掉屬整潔不裁 |
| 第 49 項 | 對照查詢輪次編號：改必填／維持 | 選 A：改必填 | get_wf_ids_by_control_ids round_id 必填；套件一行、同次發版 |
| 第 50 項 | 任務入口與批次（U7）：掃／不掃 | 選 A：掃 | U7 進下階段主專案掃描（決策者 2026-09-25 裁） |
| 第 51 項 | 權限共用層那句：照盤點更正（點頭／不點頭） | 選 A：更正 | 總表 §0.5 補句；common/authz 排 U1 第一棒 |
| 第 52 項 | 系統設定守門補掃：併 U12／單獨一棒／不補 | 選 A：補掃 | 併 U12 |
| 第 53 項 | 組裝檔專掃：工具掃 17 支／工具掃全部／腳本對照全部 | C 先、A 後、B 不做 | 先開實作卡寫腳本比對 75 支建構參數 vs 容器參數；U13a／U13b 兩棒帶著腳本結果掃 17 支沒碰過的 |
| 第 54 項 | 人員對帳跨公司比對：補併 U12（點頭／不點頭） | 選 A：補 | 併 U12（與第 52 項合計約 1,770 行） |
