FR-119 交修正線清單——十九件裁定+掃描重啟後修正卡缺口(給 FR-114 首腦)

交修正線清單:掃描線要交給 FR-114 的全部東西

整理卡 CM-2150(母卡 CM-2139)|整理日期 2026-09-25|只整理、不執行:沒有開卡、沒有改 FR-114 任何檔、沒有改總表。 出處:總表 docs/features/security-scan-consolidated/README.md(§3.1 第 118~180 項、§4 分組、§7 第 33/35 項)、裁定表 decision-draft.md 末尾、FR-116/FR-118 站 README「修正線要接的」、各棒報告。「修正分支現況」欄是本棒 2026-09-25 開 fix/security-b1 工作區(BE HEAD 9ff0a5060、套件 HEAD ab68291b)實查的結果。

§1

這份給誰、怎麼用

讀者:FR-114 首腦。你懂程式、但沒看過掃描線 09-21 重啟後那 40 棒報告。 用法:四段各一張表,一列一件,讀完就能開卡。

  • 第一段:你已經做完的卡,被掃描線查出缺口或被決策者裁退回的。要重開或補卡。
  • 第二段:第 118~180 項裡還沒有卡的,已按同卡關係併好。每組一張新卡。
  • 第三段:十九件裁定照抄,每件加一句「修正線要做什麼」;最後是套件發版清單。
  • 第四段:決策者裁「拆掉」的網址,列出拆之前要確認的事與要一起拆的東西。
  • 最後一節是決策者已裁、不要重問的清單。

幾個詞:

  • 守門:程式裡檢查「你有沒有資格做這件事」的那段。
  • 修正分支:fix/security-b1,FR-114 的工作區,還沒合回主線。
  • 出貨基線:新客戶安裝時拿到的資料庫結構(scripts/init/02-schema.sql)。動了資料庫結構或隔離規則就要重產;重產屬決策者裁示。
  • 發版:改了 jedi-* 套件就要發新版,主專案才拿得到。

🔴 開卡前先看這四件:

  1. 第 154 項是本批唯一「不必登入」的高風險,而且你已經發出去的 jedi-common 1.3.0 讓它慢了約 8 倍(CM-2065 改了同一段比對)。正式版 1.21.0 前必須修。見第一段 1-6。
  2. CM-2037 要退回:稽核團隊名單的修法擋不住跨客戶(第 42 項已裁)。見第一段 1-1。
  3. 第 66 項已升為高,但稽核計畫選單與儀表板兩支不在 CM-2037 範圍、沒有卡接。見第一段 1-2。
  4. 總表第 133 項登記的舊修法是錯的,照舊修法修等於沒修。見第一段 1-7。

§2

第一段:你已做完、但要補或退回的卡(8 列)

# 哪張卡 缺口是什麼(白話) 在哪裡 怎麼修 決策者裁定 開卡建議
1-1 CM-2037(2-5,Done) 🔴 稽核團隊名單「查得到輪次才檢查你是不是專案成員」。別家客戶的輪次被資料庫隔離藏起來、查回來是空的,於是整段檢查跳過、名單(姓名/Email/電話)照樣回去。擋住了同客戶跨專案,沒擋住跨客戶 修正分支 app/flow_control/service/assessment_plan_app_service.py:714-722 list_ap_parties(本棒實查::719 if curr_user_id is not None、:721 if rnd is not None) 查不到輪次就回 404。照同檔另一支 resolve_ap_and_check_participant 的寫法。curr_user_id 也要一起改必填(見 1-4) 第 42 項:退回 CM-2037(主專案改、不發版) 退回 CM-2037;可與 1-2、1-4 同一棒
1-2 CM-2037 範圍外(第 66 項,已升高) 稽核計畫選單與儀表板兩支只查登入、不查專案成員。儀表板還不比對「這一輪是不是這個專案的」。CM-2037 只修了 audit_round_route.py 那 8 支,這兩支沒卡接 api/flow_control/routes/assessment_plan_route.py:38 選單 GET、:108 ApDashboardResource.get;repo infra/flow_control/repository/flow_control_project_repo_impl.py:511 _resolve_dashboard_round_id(:549/:632 兩處呼叫) ①選單與儀表板在服務層補「是專案成員」檢查(走 common.authz 的 assert_project_participant);②_resolve_dashboard_round_id 解出輪次後比對 project_id 等於網址專案,不符就回 404 無(修法無爭議) 新卡,與 1-1 同批(同一支檔、同一種漏)
1-3 CM-2041(2-9,Done) CM-2041 修了第 118/119 項的兩支刪除,但第 129 項零修法:把程序書掛到控制項時,文件編號換內部 ID 那一步查的是全系統,沒限定「只能是這份計畫池子裡的」。可以把別人的文件掛過來、再從回應拿到檔案代號去下載(同客戶跨專案) 主專案 app/oscal/service/ssp_document_pool_service.py:159 add_control_mappings(本棒實查:resolve_doc_uids_to_ids(doc_uids) 沒帶計畫範圍);套件 jedi-compliance-audit infra/repository/ssp_document_pool_query.py:205-206。查核項目那支掛載方法同病、要一起改 把計畫範圍傳進 resolve_doc_uids_to_ids(),查詢條件加「屬於這份計畫的池子」。樣板照抄 app/module_frame/service/module_frame_reference_document_service.py:161,173 的 _get_doc_or_404。要改套件 無 新卡(或補 CM-2041);jedi-compliance-audit 要發版
1-4 CM-2037 的寫法 套件守門寫成 curr_user_id: int = None、「有傳才檢查」。以後任何新呼叫端忘了傳,會安靜放行、不報錯 套件 jedi-compliance-audit:app/service/audit_round_app_service.py:223 list_rounds、:232 get_round、:900;poam_app_service.py:257 list_items、:284 get_item;assessment_result_app_service.py:404 get_findings、:709 list_risks(本棒實查共 7 支)。主專案 list_ap_parties(1-1)同型 7 支+list_ap_parties 的 curr_user_id 拿掉預設值改必填,呼叫端全部補傳 第 38 項:改必填,修正分支上順手改、合回前;套件要發版 併 1-1 同一棒(同是 CM-2037 退回範圍)
1-5 手測陷阱(非缺口,是驗收會驗錯) 開發機主 checkout 的 .venv 有 12 個 .pth 指到修正分支的套件工作區,但主 checkout 的路由還是舊的、沒傳 curr_user_id(本棒實查:主 checkout audit_round_route.py 24 處 vs 修正分支 32 處)。在主 checkout 手測「輪次讀取守門」,套件新守門一次都不會觸發,會誤判成「沒修好」或「修好了」 主 checkout .venv/lib/python*/site-packages/*.pth;總表 §0.5「已修要打折看」 輪次守門手測只在修正分支工作區或 190(1.21.0b2)做。合回後照 FR-114 STATE 第 5 步清掉那 12 個 .pth 無 不開卡;寫進 1-1 那張卡的驗收段
1-6 CM-2065(5C-4,Done,已發版) 🔴 第 154 項(高,不必登入):每個請求在檢查身分之前,攔截器就把請求內容拿去「遮密碼」,那段比對遇到特製內容越算越久,幾個請求就卡住全部工人、所有客戶停擺。CM-2065 改了同一段比對(加上吃 JSON 跳脫序列),讓它再慢約 8 倍。jedi-common 1.3.0 已含 CM-2065(本棒實查 tag jedi-common-v1.3.0 包含 a9562dd0),190 上的 1.21.0b2 已經帶著這個惡化版 套件 jedi-common jedi_common/utils/common_utils.py:145 mark_password(比對規則 :159-160);主專案 common/middleware/app_mw.py:167(寫日誌)、:172(寫 api_log),都在遮罩前沒限長度 兩層:①套件把比對規則改成線性時間的寫法(根因);②攔截器遮罩前先截長度,超過就截斷並標「已截斷」。修完用同一組長度重測,確認耗時與長度成正比 總表 §7 第 33 項:發版前必須一起修(決策者要求轉告 FR-114) 新卡、排最前;jedi-common 要發版(1.3.1),BE 改 pin。建議與 2-O 同卡(同一個攔截器,見第二段)
1-7 總表第 133 項的修法(總表登記的舊修法錯了) 第 133 項(刪框架/刪版本不檢查還有沒有客戶在用)總表舊修法是「照叫編輯路徑那支 _require_no_references()」。但那支查的是「基準線指向公版目錄」,而建資源庫一律先複製再引用副本,正常流程永遠零筆(DEV 591 筆基準線、指向公版 0 筆)——照原修法等於沒補。編輯公版目錄那六支、匯入覆蓋那一道呼叫的也是同一支,從來沒擋過東西 刪框架 app/oscal/service/framework_app_service.py:185、刪版本 framework_version_app_service.py:224;編輯路徑 framework_version_edit_service.py:207/218/230 呼叫、:258-266 定義;匯入覆蓋 framework_parse_job_service.py:386-403;正確該查的欄 compliance.module_frames.oscal_framework_version_uid(resource_library_app_service.py:512 寫入) 三處(刪版本/編輯公版目錄/匯入覆蓋)改成用系統層跨客戶查詢查 module_frames.oscal_framework_version_uid 有沒有未刪除的資源庫在用,有任何引用就拒絕。「版本必須是草稿」那道照舊留著 第 46 項:三處同卡換;第 133 項維持中 新卡(主專案,不發版)。同卡可順手記「刪主版本、刪有子版本的版本會吐 500」(非資安)

| 1-8 | CM-2052(代理程式通行證,Done)連帶 | 🔴 修正線啟動會炸:09-23 修 CM-2052 那顆 commit(套件 monorepo c4acc687)給 jedi-remote-agent 的 AgentTaskService 建構子加了一個必填零件 remote_agent_domain_service,但修正線 BE 的組裝表沒跟著接。修正線一啟動、走到代理程式任務那條路,會直接建構失敗(TypeError 缺參數)。這是修正線自己的 bug,不是掃描線發現的資安問題,FR-120 DI 比對腳本跑修正線基準時抓到的 | 修正線 BE worktree di_containers/agent_task/agent_task_containers.py:36 agent_task_service = providers.Factory(AgentTaskService, ...) 只給 agent_task_domain_service 與 lifecycle_listener;套件端 jedi_remote_agent/app/service/agent_task_service.py:47 宣告必填 | 在那個 Factory 補 remote_agent_domain_service=remote_agent_container.remote_agent_domain_service(主專案 di_containers/flow_control/flow_control_containers.py:437 已有同樣接法可抄) | 無(不是裁定項,是合回前必修) | 併回 CM-2052 或開一張連帶卡;合回主線前必修。兩份比對表:主線基準 docs/features/FR-120-2609-host-residual-security-scan/di-wiring-audit.md、修正線基準同資料夾 di-wiring-audit-fixline.md(「必填缺接」那節就是這一處;「🔴」那節多出的 4 處是修正線新加零件在修正線容器沒接,一併核) |

跟 FR-114 STATE 的衝突:STATE §1 寫「程式面 50/53 全 Done」「已發版 18 支套件」。1-1、1-3、1-4、1-6 會讓 CM-2037/CM-2041/CM-2065 三張 Done 卡重開或出新卡,jedi-common、jedi-compliance-audit 需要再發一版;1-6 會影響 STATE §2 第 13 條「正式 1.21.0 前必做」——建議把第 154 項加進那條清單。


§3

第二段:第 118~180 項還沒有卡的,建議怎麼開(21 張)

從新卡清單剔除的(不要派):

項次 為什麼剔除
第 118/119 項 CM-2041 已修在修正分支(套件 delete_by_uid 本身仍只認編號,已登記為 CM-2041 的已知限制,不另開)
第 122 項 CM-2055 已修(修正分支 f85a82edb:ssp_docx_generator.py:62 autoescape=True)
第 126 項 CM-2055 已修(同 commit:ssp_control_impl_import_service.py:140/164 改用 set_text_cell)
第 159/160 項 已修:第 159 項 CM-2113(job_force_start_service.py:139 核對任務屬於網址專案)、第 160 項 CM-2148(:59 補成員檢查)
第 166/167 項 第 36 項裁拆網址,見第四段 4-1
第 170 項 第 43 項裁拆網址,入口消失、問題跟著消失,見第四段 4-2
第 129 項 已列在第一段 1-3(CM-2041 缺口)
第 133 項 已列在第一段 1-7
第 154 項 已列在第一段 1-6
第 168 項 修法由第 37 項裁定決定,排在 2-P(下表),不是剔除

每一列=一張建議新卡。 「發版」欄寫要發哪支套件;「基線」欄是出貨基線要不要重產。

卡 項次 一句話 嚴重度 該補檢查的位置(檔:行) 併卡理由 發版 基線
2-A 120+123+125+134+137+138+153 🔴 合規範本寫入有七處漏守:編控制項清單、Excel 匯入覆蓋、Word 匯入覆蓋三條路不檢查權限與歸屬;編輯範本時改「分享範圍」有檢查、改「內容」沒有;改流程圖的檢查包在 if 裡;刪改子項檢查網址編號、動手改另一個;只有「建立」權限能用 Excel 匯入覆蓋既有範本 高×3(120/123/125)、中×4 120:app/oscal/service/resource_library_app_service.py:364/412(+同路徑 _init_ao_workflows);123:ssp_excel_import_app_service.py:803-817 上傳端、:441/:478 確認端;125:ssp_docx_import_app_service.py:138-166 上傳端、:335 確認可換目標、:358-387;134:app/module_frame/service/module_frame_service.py:117(守的那半在 :112);137:module_frame_item_service.py:62-65 檢查移到 if 外、:84 寫入;138:module_frame_item_service.py:161(改)、:229(刪)、:247;153:module_frame_import_service.py:124-129(is_update 為真時加查 module-frame.update) 同一塊地(合規範本寫入),總表明寫「三條必須一起修,只補一條另外兩條照樣進得去」;153 底下直接呼叫 134/138 那兩支 無(主專案) 否
2-B 128+149 🔴 SSP 匯出成 Excel 範本只查「你能不能讀資源庫」、不查「這份計畫是不是你的」,跨客戶一個 GET 就下載整份計畫;空白範本附帶全公司 email、設備 IP、資訊系統清單 高(128,跨客戶)、低(149) 128:app/module_frame/service/ssp_import_template_app_service.py generate_for_ssp 第一行補 require_participant(ssp_uid)(照隔壁 export 抄,DI 在 di_containers/module_frame/module_frame_containers.py),入口 ssp_import_template_route.py:82-110;同檔 generate()(:223)順手補程式層檢查;149:同檔 :600 方法、:640-641 撈下拉資料改依呼叫者權限縮減 同一支服務檔,總表第 128/149 項都寫「修第 128 項時順手補」 無 否
2-C 135+136+139+140+141+142+143+144+145 範本模組九項、十二個讀取入口不檢查權限,其中人員名單、設備清單、系統元件、繼承授權、系統特性跨公司都讀得到 中×8、低(145) 全部補 @require_capability("module-frame.read"):135 api/module_frame/routes/module_frame_route.py:25-27、:45-47;136 module_frame_item_route.py:31-33;139 module_frame_reference_document_route.py:61-63;140 module_frame_control_objective_default_route.py:50-52、:109-111;141 module_frame_party_route.py:26-28;142 module_frame_inventory_route.py:19-20;143 module_frame_components_route.py:19-20;144 module_frame_leveraged_route.py:30-31+module_frame_system_characteristic_route.py:29-30;145 module_frame_ssp_resources_route.py:32-34 同一批讀取入口、同一行修法,總表要求一張卡。⚠️ 先確認 module-frame.read 權限點存在且現有角色都拿得到,否則症狀是永遠 403 且畫面沒錯誤訊息;135 選單那支的角色設計要先問決策者(總表第 135 項左欄);145 runner 另建議補 api/oscal/routes/module_frame_template_ssp_route.py,待決策者定 無 視權限點種子:若要補種子 migration → 要重產
2-D 146+147 **範本底下六類附屬資料寫入、Excel 批次存檔控制項清單,只問「查得到嗎」不問「是不是你家的」 中×7 146:六支服務的 _template_ssp_id() 解出範本後各加 assert_scope_writable(mf.tenant_id, mf.scope)(module_frame_party_service.py:86、module_frame_components_service.py:72、module_frame_inventory_service.py:77、module_frame_leveraged_service.py:84、系統特性、SSP 資源各一);147:module_frame_template_import_service.py:329 補同一行,同批補 validate_items(:265)與兩支下載(:173/:187) 同型(查得到就放行),總表建議合成一張橫向卡;六支要一起補,補五支等於沒補** 無 否
2-E 121+175 建資源庫的入口只驗登入;而且不檢查框架版本發佈了沒,草稿也能拿去複製 中、低 121:api/oscal/routes/resource_library_route.py:50 補能力點(範本 ModuleFrameRoute.post),Excel 匯入、Word 匯入那兩條建資源庫的路也要一起補;175:resource_library_app_service.py:460-467 在 get_version 之後補「必須已發佈」,補這一支三個入口一次蓋到 同一支 create_resource_library,FR-118 README 修正線第 1 件 無 否
2-F 124+127+130+176+179 壓縮炸彈四個入口、兩個 repo:SSP 的 Excel/Word 上傳、稽核計畫 Word、稽核結果 Excel 都只量壓縮後大小,解開整份塞記憶體;稽核結果 Excel 還一路讀到上傳者決定的最後一列(4.9KB 檔吃 355MB) 中×5 主專案:app/oscal/service/excel_parser/parser.py:42(read_only=False,124/130 同一行)、ssp_excel_import_app_service.py:124-126;ssp_docx_import_app_service.py:50/131 限制、:759 解析(一份上傳會被打開三次,檢查要放第一次開檔前)。套件 jedi-compliance-audit:import_adapter/registry_base.py:24(176)、ar_report_parser/airasia_cmmc_l1_ar_v1.py:162-164+registry.py:17(179) 總表明寫「病灶四個入口兩個 repo、共用同一支檢查函式、同一張卡」;FR-116 README 修正線第 4 件。上限數字參考 config/config.py:194-200,但那組是照檢測規則包訂的,合不合適由開卡的人判斷 jedi-compliance-audit 否
2-G 173 一份幾 KB 的特製 Word 讓 SSP 匯入解析卡到 120 秒逾時,四個請求讓整個 API 對所有客戶停擺,六個位置 中 domain/oscal/parser/docx_section_extractors.py:538-541、:545-549、:74-86;domain/oscal/parser/control_id_matcher.py:20、:50-76;轉接器「標籤:值」切法與兩處找排第幾(詳見總表第 173 項) 🔴 兩支檔各有一條比對規則,同一份檔會先後跑到,只修一邊等於沒修——驗收要用同一份惡意檔從上傳整條跑一次,不能只各自單元測試。與 2-A 第 125 項、2-F 第 127 項同一條上傳路,排程一起看 無 否
2-H 131+152+177 比對規則沒防長輸入:Excel 版本號那格(跑在版本檢查之前,不用合法範本)、Excel 範本匯入檢核的網頁標籤比對、稽核計畫 Word 解析器三條規則,送超長字串就卡住一條工人 中(131)、低×2 131:app/oscal/service/excel_parser/parser.py:143/148/151-153——最好直接刪掉這份、改用既有的 version_check.parse_semver;152:app/module_frame/service/module_frame_import_service.py:52 開頭擋長度、:23 規則改 <[^<>]{1,200}>;177:套件 ap_report_parser/airasia_cmmc_l1_v1.py:57/:62/:107-113,:205 起先截長度 同型,總表寫「一起修」 jedi-compliance-audit(177) 否
2-I 171+172 特製的 CMMC PDF 把解析拖垮:頁數沒上限、每頁不釋放;目錄行比對遇超長一行平方級變慢 低×2 套件 jedi-oscal-v2:infra/adapter/base_parser_adapter.py:37-57 開檔後先擋總頁數、每頁 page.close();infra/adapter/cmmc/cmmc2_lv2_parser_adapter.py:73 _TOC_PATTERN、:81 開頭 len(line) > 500 直接當內文、:407 改 str.find。主專案 framework_parse_job_service.py:215 前可再擋一次 同一支檔、同一次發版;第 45 項裁與 jedi-oscal-v2 依賴清理同次發版 jedi-oscal-v2 否
2-J 132+174 解析失敗把原始錯誤訊息回給前端:PDF 那側吐套件結構與 SQL,Word 那側吐伺服器暫存檔完整路徑 中、低 132:app/oscal/service/framework_parse_job_service.py:228 拿掉 : {e}(本棒實查仍在),:215-219 那個 try 也包住寫資料庫、一併涵蓋;174:domain/oscal/parser/docx_parser_core.py:23(訊息不接 original)、:171-172/:193-194,服務層 ssp_docx_import_app_service.py:220/:226 不用 str(e) 同一種修法,總表 §4 🅶 組寫「一張卡兩邊一起改」 無 否
2-K 148+150 Excel 範本公式注入:上傳時塞進去的公式、或任何人把自己暱稱改成公式,會在別人下載範本開啟時執行(連空白範本也算) 中×2 改用 jedi-common 的 set_text_cell(已在 1.3.0,本棒實查 export_safety.py:29),五處六行逐一列成驗收項:app/module_frame/excel_template/lookup_builder.py:47、:91、:93;generator.py:578、:319、:247(本棒實查這兩支檔尚未用 set_text_cell)。⚠️ generator.py:543 _apply_autofill_formulas 是系統刻意寫的公式,不能一起改;只修 578 會守一半 總表 §7 第 31 項已裁「合一張卡」,含帳號模組的使用者匯入範本;上傳端 sheet_handlers.py:64 已裁「只記警告日誌、不改內容」(§7 第 32 項) 無(jedi-common 1.3.0 已含 set_text_cell) 否
2-L 151 幾 KB 的 YAML 讓伺服器算到當掉(引用展開無上限) 低 infra/module_frame/adapter/yaml_to_module_frame_parser_adapter.py:14 parse 開頭改自訂 SafeLoader、遇 alias 拒絕;:35 加層數與節點數上限;格式錯目前炸 500 要改回「格式錯誤」 單獨一張(也可併 2-H 同一輪) 無 否
2-M 155+156+157+158 規劃頁任務的四個入口不核對「這張任務屬不屬於網址上那個專案」:清單、批次匯入確認(可順便改別的專案的任務)、匯出、匯入驗證兩步 中×2、低×2 155:app/flow_control/service/job_service.py:269 list_jobs 開頭補 assert_project_participant、專案編號改必填(本棒實查未修);156:job_import_service.py:398 confirm_import、白名單 :413 改用「這個計畫底下的任務」並核對計畫的專案=網址專案;157::104 export_excel 核對計畫的專案=網址專案;158::198 validate_import、:315 revalidate_items 開頭補「計畫屬於網址專案+你是成員」(本棒實查四支都未修) 總表 §4 🅰「第八種長相」:五個入口要逐一列驗收項。決策者原裁第 156 項併 FR-114 卡 2-7(CM-2039),但 2-7 已 Done,所以改開新卡;第 159/160 項已修(見剔除表)。「任務屬於哪個專案」的判斷請用 CM-2113 的唯一歸屬判斷(resolve_project_id_for_job),見本段末 無 否
2-N 161 「AI 金鑰只限平台管理員」開關一放開,原廠 AI 金鑰會被送到客戶自己指定的伺服器(今天打不到) 中 app/system_config/service/ai_provider_key_resolver.py:133/:154(位址跟金鑰同層取);app/system_config/service/tenant_storage_config_seeder.py:52-55(新租戶不抄金鑰);開關說明 common/constant/ai_service_config.py:29 單獨 無 否
2-O 163+164 操作日誌兩個洞:網址加長就不留紀錄(欄位超長寫入失敗);來源 IP 全記成前端代理 中、低 163:common/middleware/app_mw.py:160-197 寫入前把所有有上限的欄位截斷(網址 500、IP 255、瀏覽器資訊 5000),寫入失敗至少留一筆替代紀錄;164:app_mw.py:189、common/integrity/adapters.py:268-272、jedi-iam jedi_iam/api/routes/login_route.py:26 三處統一,不能直接改讀 X-Forwarded-For,要讓後端只信 nginx 那一跳 同一個攔截器;決策者已裁「同卡截所有欄位」「三處讀 IP 一起統一」。建議與 1-6 第 154 項同卡(同一個 before_request) jedi-iam(164 那處) 否
2-Q 162 證據分類跑超過 30 分鐘逾時,原廠 AI 金鑰以明文寫進後端日誌 中 套件 jedi-evidence-classification infra/classifier_container_runner.py:189-190(raise ... from None,更根本改 --env-file);主專案 infra/support/diag_masking.py:164 _LOG_SECRET_LINE_RE 補認 KEY=值 ⚠️ 套件那半要照外部套件異動規範先提醒、決策者點頭才動 jedi-evidence-classification 否
2-R 165 沒買問卷模組的客戶照樣能用問卷的「填答」那半(14 支方法沒掛授權檢查) 低 套件 jedi-survey api/routes/task_survey_route.py、question_answer_route.py、question_answer_history_route.py、question_answer_history_detail_route.py,每支 @jwt_required() 下加 @require_license("survey")(行號見 FR-115 W1 報告總覽表) 決策者已裁三個入口一組一張卡 jedi-survey 否
2-S 169 把稽核「判定」接到「風險」時,套件不檢查兩者是不是同一份稽核結果(唯一呼叫端有擋,是地雷) 低 套件 jedi-oscal-v2 app/service/assessment_risk_service.py:109-125 link_findings 開頭逐一比對 ar_result_id、:132-143 get_risk_findings 同樣過濾;呼叫端現有那道留著 守在套件;可併 2-I 同次 jedi-oscal-v2 發版 jedi-oscal-v2 否
2-T 178 兩張「解析工作單」表的資料庫隔離規則是 5 月已判定壞掉、SSP 那張早修掉的舊寫法,7 月建表照抄——DEV 實測子公司看得到母公司的工作單 低 scripts/sql/2026-07-02-ap-docx-parse-jobs.sql:40-42、scripts/sql/2026-07-03-ar-xlsx-parse-jobs.sql、scripts/init/02-schema.sql:24943。照 2026-05-01-fix-ssp-docx-parse-jobs-rls.sql 改成 app_tenant_allowed_for_session(tenant_id)+超級管理員放行 兩張表一起修(FR-116 README 修正線第 5 件) 無 🔴 要重產(新 migration,屬決策者裁示;只套 DEV)
2-U 180 確認匯入稽核結果時,佐證資料照前端送來的存、不核是不是這一輪的 低 主專案 api/project/serializers/ar_import.py:38;套件 jedi-compliance-audit ar_import_app_service.py:301、assessment_result_app_service.py:552-580:確認時比對工作單存的候選池、連結只收 http/https;一般新增觀察網址 audit_round_route.py:286-311 同修 🔴 檔案那半要等總表第 34 項(檔案預覽補歸屬檢查)才真正關得起來,開卡時寫明依附 jedi-compliance-audit 否
2-P 168 **專案經理能改寫、再刪掉稽核人員寫的「改善建議」 低 主專案 api/project/routes/audit_round_route.py:440 RiskRemediationsRoute.post、serializer api/project/serializers/audit_round.py:211-212(uuid/lifecycle 無值域限制);套件 poam_app_service.py:310 add_remediation 第 37 項已裁「稽核方專屬」:類型是「建議」那筆拒絕覆蓋、拒絕刪除**,不做另存留痕 jedi-compliance-audit 否

特別標的幾件(卡上要寫清楚):

  • 第 154 項(第一段 1-6):唯一不必登入的高風險,排最前。
  • 第 66 項升高(第一段 1-2):判定矩陣、風險清單、改善計畫四支讀取內容比輪次清單機密得多,三人面板一致評高;底下六張 oscal 表資料庫隔離全關,程式這一關漏了沒有備援。
  • 第 173 項(2-G):六處同卡,兩支檔的比對規則只修一邊等於沒修。
  • 第 176 項(2-F):壓縮炸彈四入口兩 repo,併第 124/127 項。
  • 第 178 項(2-T):壞隔離規則兩張表,出貨基線要重產。
  • 第 171/172/177/179 項:資源耗盡,分在 2-I、2-H、2-F。
  • 第 169 項(2-S):守在套件,不是呼叫端。

「任務屬於哪個專案」要不要再裁:總表 §7 第 35 項寫 CM-2108「方案待決策者裁」,但 FR-114 LOG 第 5 棒記載決策者已裁「掃描線 CM-2108 插單四件同批」,CM-2113(輪次鏈唯一判斷)已 Done。看起來總表那句已過期,2-M 直接用 CM-2113 的判斷即可——請首腦開卡前對照 CM-2113 卡確認。本棒不改總表。

數字:第二段 21 張新卡(2-A~2-U),加第一段新卡/重開 6 件(1-1 退回、1-2、1-3、1-6、1-7、1-8;1-4 併 1-1,1-5 不開卡),合計建議 27 張。若 2-L 併 2-H、2-S 併 2-I、2-O 併 1-6,可壓到 24 張。

第 118~180 項 63 條逐條去向(本棒腳本核過,無遺漏無重複):新卡 2-A~2-U 涵蓋 51 條;第一段 3 條(第 129、133、154 項);拆網址 3 條(第 166、167、170 項);已修 6 條(第 118、119、122、126、159、160 項)。


§4

第三段:十九件裁定結果(照抄裁定表,不改判)

項次 一句話 裁定 備註(照抄) 修正線要做什麼
第 36 項 任務設定樹、目前 SSP 兩支網址:補守門/拆 選 B:拆網址 與第 44、43 項同批;套件 api/routing.py 拆兩支、要發版 開拆網址卡(第四段 4-1),jedi-compliance-audit 發版
第 37 項 改善建議:稽核方專屬/經理可改但留痕 選 A:稽核方專屬 第 168 項修法=類型是「建議」那筆拒絕覆蓋與刪除;不做另存留痕 開 2-P
第 38 項 修正分支守門參數:改必填/維持選填 選 A:改必填 修正分支 fix/security-b1 順手改,FR-114 合回前;套件要發版 第一段 1-4,併進 CM-2037 退回
第 39 項 回退標記讀取:列死碼/先問產品 選 B:不清、記功能待補 階段回退作廢表已寫、讀的那半沒接;功能上不會抓錯(輪次 ssp_id 決定現用);記「凍結歷史標記作廢/瀏覽」功能待辦,三支讀取保留 不歸修正線。三支讀取方法不要當死碼清掉
第 40 項 複製 SSP 參照:修程式不補快照/修程式也補快照/先不開卡 選 A:修程式、舊快照不動 §3.2 第 36/37 項同卡修在套件;DEV 47 份凍結快照留著不清不補(凍結證據不事後動);STG/POC 出貨前視情況再查 開一張非資安卡(總表 §3.2 第 36+37 項,修在 jedi-oscal-v2 ssp_clone_service.py:170-176、oscal_io_service.py 再匯入那幾處);修第 37 項前先用一份 Word 在 DEV 跑兩次確認。不寫資料修補
第 41 項 凍結保護:套件加第二道/維持一層 選 A:套件加第二道 凍結是套件自己定義的(snapshot_ssp/FROZEN_STATUS「immutable marker」),套件 update_* 自己擋 frozen;與第 45 項同次發版 jedi-oscal-v2 ssp_service.update_* 遇已凍結就拒絕(先確認凍結當下那一步不會被擋),與第 45 項同卡
第 42 項 CM-2037 團隊名單:退回改 404(點頭/不點頭) 點頭:退回 CM-2037 list_ap_parties 改「查不到輪次就 404」;主專案改不發版 第一段 1-1
第 43 項 稽核中重排:一律走退回/允許重生 選 B:拆網址 generate-draft 前端零呼叫、後端只有該路由呼叫、v1.20.0 release note 已點名退役;連同 launch-audit/start-auditing/ar/finalize 三支一起裁;e2e step 同拆;第 170 項隨之消失 開拆網址卡(第四段 4-2)
第 44 項 更新稽核計畫網址:拆/補守門 選 B:拆網址 與第 36、43 項同批 開拆網址卡(第四段 4-3)
第 45 項 套件依賴清理:同次發/分開發 選 A:同次發版 jedi-oscal-v2:第 171/172 項修+defusedxml 補宣告+拿 pyyaml/ImportType.YAML,JSON+第 41 項凍結第二道+§3.2 第 36/37 項,一次發 套件 pyproject.toml:15 補 defusedxml、拿掉 pyyaml,順手拿掉 ImportType.YAML/JSON;與 2-I、第 41、40 項同一次 jedi-oscal-v2 發版
第 46 項 另兩道引用檢查:同卡換/只修刪除 選 A:三處同卡換 刪版本/編輯公版目錄/匯入覆蓋三處改查 module_frames.oscal_framework_version_uid,有任何客戶引用即拒絕;理由是保護稽核依據可追溯(業界慣例已引用版本不硬刪);第 133 項維持中 第一段 1-7
第 47 項 捨棄解析工作單:收緊/維持 選 A:收緊 捨棄解析工作單改稽核員或管理者,與 Excel 側一致;套件一行、同次發版 jedi-compliance-audit ap_docx_import_app_service.py:172 守門換成 resolve_ap_and_check_auditor
第 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 必填;套件一行、同次發版 jedi-compliance-audit wf_control_mapping_lookup_query.py:30-53 的 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 行) 不歸修正線

套件發版清單

照目前修正分支版號(pyproject.toml)往上推;版號由 FR-114 首腦依實際改動定。發版前同一支套件的改動全部做完、驗完才發(FR-114 STATE 已知的坑:iam 補發三次)。

套件 現在版號 這一包含什麼 建議下一版
jedi-oscal-v2 2.4.0 第 171/172 項(2-I)+第 45 項依賴清理(defusedxml 補、pyyaml 拿、ImportType.YAML/JSON 拿)+第 41 項凍結第二道+§3.2 第 36/37 項(第 40 項)+第 169 項(2-S,可選同包) 2.5.0(有新行為:凍結拒寫)
jedi-compliance-audit 1.2.0 第 36 項拆兩支網址(4-1)+第 38 項 7 支 curr_user_id 必填(1-4)+第 47 項捨棄收緊+第 49 項 round_id 必填+第 37 項/第 168 項建議不可覆蓋刪除(2-P)+第 129 項掛載限計畫(1-3)+壓縮炸彈與列數上限(2-F 的 176/179)+第 177 項(2-H)+第 180 項(2-U) 1.3.0(拆網址、必填參數是不相容改動,呼叫端要同步)
jedi-common 1.3.0 🔴 第 154 項 mark_password 線性化(1-6) 1.3.1,正式 1.21.0 前必發
jedi-iam 1.4.3 第 164 項 login_route.py:26 讀 IP 統一(2-O) 1.4.4
jedi-survey 1.2.0 第 165 項 14 支補 require_license("survey")(2-R) 1.2.1
jedi-evidence-classification 1.3.0 第 162 項逾時不吐金鑰(2-Q;先照外部套件異動規範取得決策者點頭) 1.3.1

§5

第四段:拆網址清單(3 組、7 支網址)

⚠️ 拆的是網址(路由),不一定是背後的方法。4-2 的 launch-audit/start-auditing/finalize 背後的套件方法也被畫面上的「階段推進」按鈕呼叫(修正分支 app/flow_control/service/oscal_stage_handlers.py:46/:62/:82),方法不能刪,只拆直打的網址。

# 網址 在哪裡 前端零呼叫的證據(本棒 2026-09-25 grep) e2e 有沒有在打 拆時要一起拆什麼
4-1a 任務設定樹 GET /project/<project_uid>/ap/<ap_uid>/task-setup/tree(第 36 項/第 166 項) 套件 jedi-compliance-audit api/routing.py:33-36(ProjectTaskSetupTreeResource);服務 app/service/task_setup_service.py:18 修正分支 FE:零命中(TaskSetupView.vue 已在 CM-2047 拆掉)。⚠️ FE feature/review 主線還有 src/views/project/TaskSetupView.vue:109 在打,合回後才消失——拆網址要排在 FE 合回之後,或同批 無(site-regression 零命中) 路由那段;套件 TaskSetupService 與 plugin/contract.py:55 那一欄、主專案 di_containers/flow_control/flow_control_containers.py:469-470、core/plugins/compliance_audit.py:123 的組裝;infra/repository/flow_control_task_setup_repo_impl.py:247 _resolve_ssp(若無其他呼叫者)。FE i18n task-setup.json 與 menu 字串可一起清。拆前確認沒有 AI 儀表板或外部整合在用(第 36 項原文要求,掃描那棒沒做)
4-1b 目前 SSP GET /project/<uid>/current-ssp-uid(第 36 項/第 167 項) 套件 api/routing.py:31(ProjectCurrentSspRoute);服務 app/service/project_current_ssp_service.py:35 FE 只剩定義沒人叫:src/config/api/api.js:263 PROJECT_CURRENT_SSP、src/service/SspService.js:189 getCurrentSspUid(),全 FE 零呼叫者 🔴 有:site-regression/support/data-factory/ssp-factory.js:13-14 getLivingSspUid() 直打,被 steps/project-management/ssp-helpers.js:9 引用。另一支同名函式 task-survey-factory.js:15 改走 GET /grc/project/{uid} 取 ssp.id,可照它改寫 路由;ProjectCurrentSspService 與組裝(flow_control_containers.py:249-250、core/plugins/compliance_audit.py:121、套件 plugin/contract.py:55);FE api.js:263 與 SspService.getCurrentSspUid;e2e ssp-factory.js 改走 /grc/project/{uid}(到 test repo 做)
4-2a 重生草稿 POST /audit-round/<round_uid>/ap/generate-draft(第 43 項/第 170 項) 主專案 api/project/__init__.py:52、api/project/routes/audit_round_route.py:172 AuditRoundApGenerateDraftRoute;服務 app/flow_control/service/assessment_plan_app_service.py:672 generate_draft_for_round(唯一呼叫者是該路由 audit_round_route.py:180) FE 零命中(api.js 連定義都沒有);v1.20.0 release note(docs/spec-site/current/release-notes/v1.20.0.md:110)已點名「前端零呼叫、只有 e2e step 在打,待開卡裁決後退役」 🔴 有:site-regression/steps/journeys/j5a-negatives.steps.js:99(「AP 重生草稿」) 路由+generate_draft_for_round 方法(後端無其他呼叫者,可一起刪);e2e 那一條 step 與對應 scenario
4-2b POST /audit-round/<round_uid>/launch-audit api/project/__init__.py:46、audit_round_route.py:92 AuditRoundLaunchAuditRoute FE 只有 api.js:213 註解與 :287 GRC_LAUNCH_AUDIT(另一條 /grc/project/.../ap/.../launch-audit 的舊常數)定義,全 FE 零呼叫者。畫面走 StageService(/project/:p/audit-round/:r/stage/advance) 🔴 有,而且是前置推進工具:support/data-factory/audit-round-factory.js:40-43 launchAudit()、ssp-factory.js:19-21;feature journeys/j4-phase-guards.feature:13/20、j5-state-machine-negatives.feature:32/42/52、modules/project-management/project-ssp-edit.feature:22;steps lifecycle.steps.js:289、j5a-negatives.steps.js:95 只拆路由,不刪套件 audit_round_app_service.launch_audit(階段推進在用)。e2e:factory 改用 advanceStage(audit-round-factory.js:254 已有、檔頭 :18-22 已寫「前置推進必須改用 advanceStage」),j4/j5 負向測試改打階段推進端點或刪除。e2e 改動量大,建議先在 test repo 開一棒改完再拆網址,否則回歸全紅
4-2c POST /audit-round/<round_uid>/start-auditing api/project/__init__.py:47、audit_round_route.py:105 AuditRoundStartAuditingRoute 同 4-2b(api.js:214 只有註解) 🔴 有:audit-round-factory.js:51-53 startAuditing();j4/j5 同上;j5a-negatives.steps.js:96 同 4-2b:只拆路由,套件 start_auditing 保留(oscal_stage_handlers.py:62 在用)
4-2d POST /audit-round/<round_uid>/ar/finalize api/project/__init__.py:73、audit_round_route.py:360 AuditRoundFinalizeRoute FE 零命中 🔴 有:audit-round-factory.js:118-120 finalizeRound();steps/journeys/j5-negatives.steps.js:41 同 4-2b:只拆路由,套件 finalize_audit 保留(oscal_stage_handlers.py:82 在用)
4-3 更新稽核計畫 PUT /grc/project/<pid>/ap/<ap_uid>(第 44 項) 主專案 api/flow_control/__init__.py:106、api/flow_control/routes/assessment_plan_route.py:51-91 AssessmentPlanDetailResource.put;服務 app/flow_control/service/project_service.py:536 update_assessment_plan(空殼,return None, False) FE 只有 api.js:204 GRC_AP 定義(註解寫 PUT),全 FE 零呼叫者 無(site-regression 零命中) put 方法+AssessmentPlanUpdateRequestSchema(若無他用)+project_service.update_assessment_plan 空殼+路由裡 Drive 改名同步那段呼叫;FE api.js:204 常數。⚠️ 同一個 Resource 還掛著 GET,只拆 PUT、不拆整個路由。同檔 DELETE 已於 2026-07-21 退役,可照那段寫法

拆的順序建議:4-3(無 e2e、主專案)→ 4-2a(一條 e2e step)→ 4-1(等 FE 合回、改一個 e2e factory、發套件)→ 4-2b/c/d(先到 test repo 把前置推進改成 advanceStage,再拆)。


§6

決策者已裁、不要重問

  1. 十九件全部裁完(2026-09-25),裁定照第三段,不重開。
  2. 第 36、43、44 項:拆網址,不補守門。
  3. 第 37 項:改善建議稽核方專屬,不做另存留痕。
  4. 第 38、49 項:選填參數改必填。
  5. 第 39 項:回退標記讀取不清,記功能待辦,不歸修正線。
  6. 第 40 項:修程式、已凍結的快照不動(不清不補)。
  7. 第 41、45 項:jedi-oscal-v2 同一次發版,含凍結第二道。
  8. 第 42 項:退回 CM-2037,查不到輪次回 404。
  9. 第 46 項:刪版本/編輯公版目錄/匯入覆蓋三處同卡改查 module_frames.oscal_framework_version_uid,第 133 項維持中。
  10. 第 47 項:捨棄解析工作單收緊到稽核員或管理者。
  11. 第 48 項:blsadmin 是測試資料,不開卡。
  12. 第 50~54 項:主專案下階段掃描範圍,不歸修正線。
  13. 第 153 項:只有「建立」權限不能用匯入覆蓋既有範本(總表 §7 第 30 項,09-24 裁)。
  14. 第 148+150 項+帳號模組使用者匯入範本合一張卡(§7 第 31 項);上傳端只記警告日誌、不改內容(§7 第 32 項)。
  15. 第 154 項發版前必須與 CM-2065 一起修(§7 第 33 項)。
  16. 第 156 項與任務其他入口同卡(原裁併 CM-2039;2-7 已 Done,改開新卡 2-M,精神不變:五個入口逐一列驗收項)。
  17. 第 163 項同卡截所有有上限的欄位;第 164 項三處讀 IP 一起統一。
  18. 第 165 項三個入口一組一張卡。
  19. 掃描線的裁定與缺口一次打包、不零碎轉——這份就是那一次。