docs/features/README.md · FR 編號 single source of truth
所有需求的編號登記,含尚未建站的。建有文件站的需求另見需求中心。
開發過程中的設計探討、實作計畫、前端規格等歷史文件。
API 模組文件(SA/SD)已搬至
docs/api/,本目錄只保留功能開發過程的紀錄。
要用看的? 建有文件站的需求都掛在 需求中心
index.html(總入口, 掃資料夾自動生成)。本頁是 FR 編號登記表(single source of truth),涵蓋所有需求 含尚未建站的;總入口只列有README.md的。
資料夾一律用 FR-<序號>-<YYMM>-<功能名> 格式:
FR-016-2604-google-drive-sync
│ │ │ └── kebab-case 功能名
│ │ └────── 提出年月(2604 = 2026-04)
│ └─────────── 流水序號(提出先後,補零到 3 位)
└─────────────── Feature Requirement 前綴
.N(如 FR-011 → FR-011.2 → FR-011.3),不佔整數號、不疊三層。
2026-05-29 一次性導入此規範,既有 33 個資料夾全數重編(見
docs/changelog/2026-05-29-tweak-feature-folder-fr-numbering.md)。
docs/features/FR-<序號>-<YYMM>-<功能名>/
├── design.md ← 設計探討 / 需求分析
├── implementation-plan.md ← 實作計畫(步驟、時程)
├── frontend-spec.md ← 前端整合規格
├── README.md ← 跨 phase tracker(選填)
└── handoff/ ← 跨 session 交接 prompt / phase 收口 SUMMARY
排序依 FR 號(子題緊接母題);實際提出時間看「提出」欄。
| FR | 提出 | 功能 | arc 關聯 |
|---|---|---|---|
| FR-001 | ≈2026-02 | 稽核生命週期整體分析 | 稽核生命週期母題 |
| FR-002 | ≈2026-02 | 稽核員儀表板 | — |
| FR-003 | ≈2026-03 | 多重 AP 支援 | 生命週期 Stage 1 |
| FR-004 | ≈2026-03 | 外部稽核 | 生命週期 Stage 2 |
| FR-005 | ≈2026-03 | POA&M 改善追蹤 | 生命週期 Stage 3 |
| FR-006 | ≈2026-03 | 多輪稽核 | 生命週期 Stage 4 |
| FR-007 | ≈2026-03 | 啟用專案 | 生命週期 Stage 5 |
| FR-008 | ≈2026-03 | 前端 API 遷移 | — |
| FR-009 | ≈2026-03 | SSP 控制項現況 | — |
| FR-010 | ≈2026-03 | SSP 程序書池 | — |
| FR-011 | ≈2026-03 | SSP 控制項批次匯入匯出 | SSP 匯入匯出 arc 母題 |
| FR-011.2 | 2026-05-18 | SSP 匯入匯出 Phase 2(全領域匯入 + 6 格式匯出) | ↳ FR-011 子(Phase 2) |
| FR-011.3 | 2026-05-22 | 專案內直接編輯 SSP | ↳ FR-011 子(Phase 2 Track C 補強) |
| FR-012 | ≈2026-03 | 任務批次匯入匯出 | — |
| FR-013 | ≈2026-03 | 批次完成任務 | — |
| FR-014 | 2026-04-06 | 稽核模組歷史開發規格 | 合併自 grc-project / job-comment / job-evidence / job-revert |
| FR-015 | 2026-04-24 | GitLab CI 自動 code review | — |
| FR-016 | 2026-04-24 | Google Drive 整合 | — |
| FR-017 | 2026-04-25 | 稽核範圍合併 | — |
| FR-018 | 2026-04-25 | ModuleFrame 範本預設 | MF defaults arc 母題 |
| FR-018.2 | 2026-05-26 | MF 範本預設 Phase 2 | ↳ FR-018 子(Phase 2) |
| FR-019 | 2026-04-26 | SSP 版本控制 | — |
| FR-020 | 2026-04-27 | 通知設定 | — |
| FR-021 | 2026-04-28 | 問卷答案去重 | — |
| FR-022 | 2026-04-30 | SSP 程序書 docx parser | — |
| FR-023 | 2026-04-30 | 問卷答案 checkpoint 最佳化 | — |
| FR-024 | 2026-05-04 | 合規框架 PDF 匯入 v2 | — |
| FR-025 | 2026-05-06 | SSP 更新 diff | — |
| FR-026 | 2026-05-12 | 專案流程引擎整合 | — |
| FR-027 | 2026-05-23 | docx 匯入一致性 | relates to FR-022 / FR-011.2 |
| FR-028 | 2026-05-24 | SSP OSCAL 對齊 | — |
| FR-029 | 2026-05-26 | 選單群組 | — |
| FR-030 | 2026-05-27 | 證據自動分類 | 證據分類 arc 母題 |
| FR-030.2 | 2026-05-29 | 證據分類支援圖片 / PDF 內容辨識(Claude Vision) | ↳ FR-030 子(多模態能力補強,流程不變) |
| FR-030.3 | 2026-05-29 | 證據分類支援 .xlsx / .pptx(本地抽文字) | ↳ FR-030 子(補檔型,sibling of FR-030.2) |
| FR-031 | 2026-05-31 | 證據分類分析結果報表(驗證報表 + 各 AO 誰對誰錯)+ run 結果入 DB | relates to FR-030(分類結果可視化) |
| FR-032 | 2026-06-04 | 系統資產盤點(資訊系統作為資產納入 SSP inventory,hybrid soft-ref) | relates to FR-018(MF 範本預設) |
| FR-033 | 2026-06-04 | 專案進度稽核事件埋點(任務完成/指派/退回 + 問卷狀態變更寫 system_logs)+ 查詢 runbook | relates to FR-013 / FR-021 |
| FR-034 | 2026-06-08 | jedi-flow-engine vs BE WorkflowExecutionService 收斂評估 — feasibility done,採方案 c 文件化結案(無第二稽核產品、BE 版架構合規;未來有第二產品改走抽 jedi-audit-workflow 層) | relates to FR-026(flow-engine 整合) |
| FR-035 | 2026-06-10 | SSP table 改名(system_security_plans* → ssp(s)_*,表名 only)— 跨 BE + jedi-oscal + 4 DB 環境,in-place ALTER RENAME |
relates to FR-028(SSP OSCAL 對齊) |
| FR-036 | 2026-06-10 | module_frame ↔︎ SSP 整併(樣板 SSP 模型)— *_defaults 折進「一份 is_template=True 的 SSP」,啟動專案 clone 樣板 SSP → 專案 SSP;消除 MF defaults 與 SSP 子表雙套 schema 維護 |
relates to FR-018(MF 範本預設)/ FR-019(SSP 版本控制)/ FR-035(SSP 改名) |
| FR-037 | 2026-06-10 | 🗄️ ARCHIVED(2026-06-14) — OSCAL 5 模型 × DB schema required 欄位盤點,後續演變成「全 OSCAL 關聯式 schema 重新設計」(45→42 表),方向已偏離原盤點原意,user 決定整個重來、不續作。成果(v2 schema + 審查報告)保留供未來重啟參考,見資料夾 SUMMARY。新一輪將另開 FR | relates to FR-028(SSP OSCAL 對齊)/ FR-036(SSP 表族整併同期動表) |
| FR-038 | 2026-06-14 | OSCAL 重新設計(接替 FR-037 ARCHIVED,整個重來) | relates to FR-037(前一輪盤點,已封存) |
| FR-039 | 2026-06-17 | 分散式檔案 Agent(證據檔案落地客戶端,雲端不託管 binary,依客戶分流到各自 agent)— demo 階段 | relates to FR-016(檔案儲存抽象)/ FR-030(證據檔案來源) |
| FR-040 | 2026-06-20 | 稽核計畫填寫(ap-authoring)優化 — 查核方法改 system_menu 可擴充 + 行程(task)鉤稽控制項/受評對象/參與人員(OSCAL task→activity 模型,related-controls / subjects / responsible-roles) | relates to FR-038(OSCAL 重新設計) |
| FR-041 | 2026-06-21 | 稽核結果(AR)填寫優化 — A 繼承 AP 查核指引進判定頁 / B 缺失→風險→矯正(POA&M)串接 / C 觀察照規劃方法引導化(順 OSCAL Observation→Finding→Risk→POA&M 四段,漸進增強既有面板) | relates to FR-040(承接 AP 規劃) |
| FR-042 | 2026-06-28 | 合規框架與客戶儲存空間脫鉤,改由系統部門集中管理 — 框架 PDF 改存「最高層 tenant」系統儲存;upload_files 加 storage_scope(system/customer),下載依「檔案 scope」解析後端(繞呼叫者 RLS);既有檔 migration 一次性搬遷;下載端補 auth、登入即可讀(全 tenant 共享) |
relates to FR-039(檔案儲存抽象 / RemoteAgent)/ FR-024(框架 PDF 匯入 v2) |
| FR-043 | 2026-07-02 | 稽核計畫 docx 匯入 — ap-authoring 上傳顧問稽核報告 docx → 解析預填行程 → 預覽修改 → 確認寫入(走既有 set_tasks/add_ap_party,零 AP schema 新欄位);parser adapter registry 支援多版本格式,v1=亞航 CMMC L1 格式 | relates to FR-040(ap-authoring 行程模型) |
| FR-044 | 2026-07-03 | 稽核紀錄 xlsx 匯入 — 稽核執行頁上傳顧問逐條檢查紀錄 → AO 判定+observation+佐證分級自動配對 → 批次寫入;FindingState 加 not_applicable(jedi_oscal_v2);NOT MET 自動建中風險;三層 adapter 架構(template×framework×共用 core,FR-043 registry 泛化) | relates to FR-043(匯入管線同族)/ FR-041(AR 填寫) |
| FR-045 | 2026-07-03 | CMMC 2.0 v2.13 (2024) PDF parser 相容性修正 — jedi-oscal-v2 CMMC adapter 單一 parser 雙格式:L1 FAR 式編號(AC.L1-b.1.i)regex alternation + [FCI/CUI Data] 標題尾綴剝除;行抽取字型分流(Cambria-Bold 標題 vs 內文)解 v2.13 疊字造成的 AO 遺失 / methods 分桶全毀;L1/L2 新舊四份 guide 都要可解析 | relates to FR-024(框架 PDF 匯入 v2) |
| FR-046 | 2026-07-04 | 客戶交付文件套件(架構顧問評估版)— 6 份正式 Word 文件(GAI-SD-01~06:架構 / API 全量規格 / DB / 權限安全 / jedi-* 套件 / 授權清單);Markdown 內容源 + 共用 python-docx renderer 管線;內容從 code / DB 程式化產生並對帳;產出 docs/交付文件/v1.8.0/ |
— |
| FR-047 | 2026-07-05 | 功能 SPEC 手冊(新人工程師導向)— docs/specs/ 兩層結構(功能群 _overview + 頁面 spec 13 節模板:UC / 權限矩陣 / 狀態機 / 前後端檔案地圖 / API / DB / 頁面邏輯資料對應 / 已知坑 / 開發驗證);md 為主 + FR-046 renderer 轉 docx 雙軌;pilot = 專案規劃頁 |
relates to FR-046(renderer 共用、GAI-SD-02/03/07 內容引用) |
| FR-048-2607-unified-auth-guard | 2026-07-07 | 全站統一授權守門機制 — 收斂 4 套散落守門 helper 至 common/authz/(platform-admin / super-admin / project-role / capability / signed-token 五軸);補 B 族(系統設定僅 JWT)+ C 族(GRC 專案寫入裸奔)守門;瀏覽器原生 GET 免 bearer 端點走簽章短期 token。設計拍板前見 docs/analysis/2026-07-07-unified-auth-guard-design.md |
relates to FR-047(SEC 桶產出)/ FR-038 2B(flow_engine 守門復活) |
| FR-049 | 2026-07-18 | 問卷流程規則(跳題)補回 + 子題 Designer 接線 — 復刻 v1 goto 跳題語意(同題組跳題 + 跳一~多個題組,混合情境原生支援)、v2 flowRules 資料形狀、填答端可見性計算引擎;順手收 D-3a 子題兩處 FE 接線。四段完成 commit 未部署;來源側模型經 user 手測拍板推翻 → 由 FR-049.1 目標側重構取代(引擎/快照/子題接線保留) | relates to site-regression bug 批次(D-3) |
| FR-049.1 | 2026-07-18 | 問卷顯示條件(目標側重構)— 跳題規則從「來源選項宣告目的地(goto_*)」翻轉為「目標題目/題組自宣告顯示條件(display_condition)」,解來源側四瑕疵(隱式副作用/漏網坑/零全局視圖/心智模型錯位);子題定為純排版附屬 + 母題卡直建入口。六決策全拍板見 design §2 | FR-049 母案續作 |
| FR-050 | 2026-07-18 | 稽核輪次階段回退(Stage Rollback)— 流程推進後可有條件返回上一步:僅相鄰上一步 / closed 不可退 / AR 已填保留+標記 / manager only + reason 必填 / UI 可見階段歷程時間軸(新表 round_stage_transitions,advance 也落)。副作用一律作廢標記不物理刪;BPMN 反向支援度為 plan 前提查證第一項。五決策見 design §2 | relates to FR-038(round 狀態機 / stage_advance) |
| FR-051 | 2026-07-21 | 規劃階段推進前置檢核 — 規劃→下一階段(launch_audit)前跑兩項軟提醒(confirm 放行,非硬擋):A 本輪證據蒐集 job 未完成(reuse get_ap_dashboard 統計)/ B 流程模板 userTask main_role 未在專案參與人員指派(BpmnUtils 列角色 vs participant role)。復用既有 handler-warning→needsConfirmation→force 機制,聚合單一彌窗;兩頁(規劃/總覽)嵌 Banner 自動涵蓋。五決策見 design §1.1 | relates to FR-038(stage_advance)/ FR-050(Banner);來源 Notion 母題 80ed + 子項 8020 |
| FR-053-2607-round-scoped-jobs | 2026-07-22 | 輪次隔離任務執行(覆核輪 job 實例化)— 根治「第二輪操作污染第一輪歷史」:job 全專案僅一批(project_start 生成一次),任務狀態/證據/聊天/問卷全掛 job 上被跨輪共用覆寫。三刀:① workflow_execution_control_mapping 加 round_id(接線 truth 從 catalog AO props 轉移至 wecm,props 保留相容)② launch_reverify 對 narrowed scope(母輪 not_met)復用 _generate_prep_jobs 核心生成新輪 execution+job ③ 讀取端(control-tree/dashboard/匯出)按輪過濾+凍結輪範圍改讀本輪 AP reviewed_controls(拆 profile 共用潛伏雷)。AR/凍結 SSP/程序書已健康不動;資源庫(範本工廠層)不動;歷史資料不遷移(user 拍板後續全刪)。調查全文見 Notion case |
relates to FR-038(engagement 模型)/ FR-050(輪次);影響面僅專案執行層 |
| FR-053.1-2607-reverify-clone-and-context | 2026-07-23 | 覆核輪承襲與脈絡(FR-053 續作,user 手測後拍板)— ①task-execution/progress 統計補輪次(第 3 刀漏網 bug)②覆核輪任務 clone 上輪配置:指派/問卷綁定/設備綁定+證據 clone(新 row 同檔案帶「承襲自第 N 輪」標記)+問卷含填答 clone(同帶承襲標記),狀態一律 TODO 起手 ③控制樹「上輪未通過」badge+控制項卡上輪判定/缺失參照(規劃頁+稽核頁,讀母輪 AR)④查證覆核輪 job PROCESSING 起手根因(應 TODO)。設計原則:第一輪資料零觸碰(clone 只讀),承襲標記讓稽核員分清沿用 vs 新補 | FR-053 母案續作 |
| FR-051.2-2607-stage-advance-prechecks-expansion | 2026-07-22 | 階段推進前置檢核擴展(FR-051 續作)— 軟提醒+log 備查模式擴到三個推進點:稽核計畫填寫(≥1 筆行程與方法)/ 稽核(所有稽核項目已回報,接 AO/task 完成度)/ 缺失改善(檢核待定義)。全軟阻擋 confirm 放行;比照 PlanningReadinessChecker 掛 stage_advance handler,考慮抽通用 checker 介面。尚未開工——等 FR-051 STG 驗收體感後走 brainstorm→design→plan。來源 Notion case 3a5346da-…-89f5 | FR-051 母案續作;relates to FR-038(stage_advance) |
| FR-052 | 2026-07-21 | 雲端整合 Tab 顯示 gate — 專案規劃頁「雲端整合」tab(index 5)只在 tenant drive status==CONNECTED 時顯示,未連接直接隱藏(fail-closed)。FE v-if gate 末 tab(不影響前 index);狀態源 tenant get_status。BE 選項:reuse 既有 GET /integrations/google-drive(建議,零改)或新 /connected 端點(待 Step 0 拍板)。三決策見 design §1.1 |
relates to FR-016(Drive 整合)/ FR-042(storage scope);來源 Notion 80fd |
| FR-055-2607-survey-export | 2026-07-23 | 問卷匯出(既有問卷內容匯出成 Excel 供再匯入)— 把已建立的問卷(題目/題型/選項/顯示條件等設定)匯出成與既有批次匯入樣板相容的 Excel,讓 user 匯出→修改→再匯入複製問卷。範圍待釐清:匯出欄位覆蓋度(FR-049.1 顯示條件等新結構能否被樣板格式承載)、跨租戶搬運情境、要不要含作答資料(傾向不含)。現況:只有空白匯入樣板下載(藏在批次匯入 Dialog 內)。尚未開工——等 user 下令走 brainstorm→design→plan | relates to FR-049/FR-049.1(問卷結構);來源 Notion case 3a6346da-…-8026 |
| FR-056 | 2026-07-26 | 檢測工具整合平台 — 租戶設定自家檢測工具(首接 OpenVAS,未來 Nessus/SonarQube)→ 任務設「檢測工具執行」+ 掃描參數 → 按開始 → 客戶端 Agent(FR-039 evidence-agent 擴充 executor)觸發掃描 → 報告自動回收成 job_evidences(source=DETECTION_TOOL,沿用 DRIVE_SYNC 模板)→ 發信通知 → 依完成模式 flag 自動完成/人工覆核。新 config schema 三表(detection_tools 目錄 / tenant_detection_tool_configs 加密憑證 / detection_tool_param_schemas 版更參數);派工走心跳夾帶待辦(D3);第一版只存報告不 parse findings(D4)。D1–D8 全拍板見 design.md §3。4 子需求 × 15 子任務分階段:.1 工具管理 config schema(地基)/ .2 任務類型+參數 / .3 Agent 派工+executor / .4 執行編排+證據+通知。討論稿 discussion.html |
relates to FR-039(Agent 認證鏈/心跳)/ FR-043·044(三層 adapter registry)/ FR-051(軟提醒);來源本 session brainstorm |
| FR-057 | 2026-07-28 | OpenSCAP 掃描工具接入(SSH 連線型態)— FR-056 續作,新增第二個檢測工具 OpenSCAP(CIS/STIG 組態合規稽核)並開出 connector 第三種連線型態 SSH(oscap-ssh 官方遠端模式:Agent 維持 Docker 作發起端,SSH 登入目標主機在其上原生執行 oscap、報告拉回)。目標主機前提=一次性裝 openscap-scanner+scap-security-guide+稽核帳號(Tenable 同款「同名專用掃描帳號」業界標準)。憑證=租戶層一組共用帳號(金鑰/密碼二擇一推薦金鑰 + sudo 提權),沿用既有加密鏈與 D9 派工下發。證據=每台一份 HTML 原樣上傳(多目標逐台掃),牽動 result 回收鏈單檔→多檔擴充(result_ref.upload_uids,向下相容)。D1–D7 全拍板見 design.md §2。3 子需求 × 8 子任務:.1 BE 地基(SSH 型態+seed+FE 欄位型態)/ .2 Agent connector / .3 多檔回收鏈(.2/.3 可並行)。討論稿 discussion.html |
relates to FR-056(檢測工具平台/connector 架構)/ FR-039(Agent);來源本 session brainstorm |
| FR-058 | 2026-07-30 | 檢測工具擴充(四工具接入)— FR-056/057 續作,一次接入 ZAP / InSpec·CINC / GCB / Nmap 四個工具,並補上平台唯一結構性缺口 任務層敏感參數(param_schema 支援 secret: true:BE 存 tool_params 前 Fernet 加密、派工時解密下發、FE 執行紀錄與稽核 log 一律剝除;D1)。ZAP 走 API/daemon 客戶自備(D3),三種 scan_mode 預設被動加攻擊流量警語(D2),PDF 上傳 + JSON 僅記憶體解析雙格式(D4),對齊 zaproxy 0.6.0 與 2.17.0 警報去重語意,舊碼參考前同事 auto-pentest(可搬 API 序列 + 12 報告模板矩陣 + 四種登入認證;必丟 DDD 分層/自起容器/報告落地;必修硬編憑證/無取消無 timeout/Nashorn)。InSpec 選 CINC Auditor(Apache 2.0,非官方商業 binary;D5)、SSH+WinRM 雙 transport 一次到位(D6),吸收並結案 Notion CM-953(異質 OS 檢測;OpenSCAP 官方棄 Windows 已證實不可行)。GCB 不另立引擎複用 .2 connector,content 格式統一 InSpec profile(D8),本案只做引擎 + 一份 Windows 最小 Demo profile,驗收=鏈路可運作非規則覆蓋量,content 產製/後台更新機制/macOS 15 全排除,但 content 外部載入接口本案就要留(D7)。Nmap 為 CLI 型態首個使用者,NPSL 授權不 bundle 進 image,需先放寬 start_execution 零憑證誤擋(detection_tools 加「是否需要憑證」宣告欄位;D9)。橫向項 _TOOL_ID_TO_CODE 解耦(派工 payload 夾帶 tool code,消除三環境 seed id 錯一位就靜默跑錯工具;D11)最先做完。D1–D11 全拍板見 design.md §2(D10 隨 SonarQube 移出本案,編號保留不重排)。1 橫向項 + 5 子需求 × 20 子任務(Notion CM-957~983,27 張卡連號)。排程=分批出貨(2026-07-30 改版,ZAP 優先上線):第一批 ID 解耦+.0 敏感參數+.1 ZAP(CM-958~970,切平台側/agent 側兩 session 並行)→ 第二批 .2 InSpec→.3 GCB → 第三批 .4 Nmap;端到端測試留到各批結束才做一次(重建 agent image+部署三台+等 300 秒心跳才是真成本)。2026-07-31 追加 SonarQube 兩棒(同一個工具、兩種模式,非兩個工具):.5 拉取快照(D13–D16,§4.6)——SonarQube Server 沒有任何觸發掃描的 Web API,故為平台首個 pull-snapshot 型工具,任務執行=拉最近一次分析結果組自包含 HTML(Community Build 無報告匯出,自組是必做非 fallback;issue 明細取前 200 條防 api/issues/search 一萬筆硬上限,統計走 facets/measures 全量)、憑證 base_url+user token(squ_;sqp_/sqa_ analysis token 不能讀)、issue 解析 impacts[] 優先 fallback 舊 type+severity 相容 9.9 LTS~2026.x LTA、probe 陷阱=authentication/validate 匿名呼叫也回 valid:true 必須帶 header、seed 是 UPDATE 既有 id=3 佔位列非 INSERT(照 ON CONFLICT DO NOTHING 會靜默跳過);T-5.1~5.3(CM-995+)程式碼已完成 commit,UI 端到端驗收未做(detection_executions 內 sonarqube 仍 0 筆)。.6 主動掃描(雛形)(D17–D24,§4.7)——決策者看到 .5 畫面後指出「要的是平台真的發動掃描」,是新需求不是 bug(D13 排除 agent 自跑 scanner 的前提是「沒有源碼」,本案補上該前提 + 收斂語言解掉「備不齊 build 環境」);D17 ZAP 式共存(同一張卡 + scan_mode 分流,非另立 tool code——GCB 式唯一優勢「憑證各自乾淨」不存在,實查兩模式共用同一組 config_field_schema 一字不改)、D18 只做 A 類純源碼 7 語言(Py/JS/TS/Go/PHP/Ruby/Kotlin;Java 送進來是硬失敗、C# 是靜默淺掃=零發現誤讀成很乾淨,故三件配套必做)、D19 公開 Git repo(0 新層;檔案上傳要動 FE 元件+upload 中繼+派工鏈路三層且 RemoteAgentAdapter 在 MINIO 租戶不存在)、D20 scanner 打進 image(zip 自帶 JRE 不裝 JDK;agent 無 docker CLI/socket,poetry.lock 的 docker 7.2.0 是 testcontainers 測試相依洩漏易誤判)、D21 一律加 Guidant-AI- 前綴、D22 只做逾時 + 磁碟型 tmp 掃完即刪(不可用 /dev/shm,那是 tmpfs 記憶體型)、D23 coverage 紅燈照實顯示、D24 scan_mode 預設 scan(與 ZAP D2 預設被動方向相反是刻意的——代價量級不同:D2 是對外部系統送攻擊流量、本案是在客戶自有系統留一筆可刪紀錄;但預設指向不可回復側故事前告知升級為必做)。兩個官方文件確認的坑:①沒有 dry-run(每次掃描都是對客戶 server 寫入、專案不存在會自動建立)②掃完≠能讀(EXECUTION SUCCESS 只代表上傳完成,須解析 report-task.txt 取 ceTaskId 輪詢 ce/task 脫離 IN_PROGRESS,否則拉到舊資料且不報錯;CE 顯示的處理時間不含排隊不能當 timeout 依據)。FE 硬編陷阱 JobExecutionDrawer.vue:308 _PRIMARY_PARAM_KEYS 需一併改(scan 模式下 Git URL 才是主要識別);模式值非法明確 raise 不靜默降級(照 zap.py:164-171)。拆 T-6.1 BE seed(param_schema v2 + setup_guide 改寫)/ T-6.2 agent(Dockerfile + scan 分支 + 輪詢 + tmp 清理)/ T-6.3 FE + 驗收,.5 的 UI 驗收併入 T-6.3 一起做(決策者:「那版基本不能用了,先不測試,要等這版」)。討論稿 discussion.html(四工具母案)、discussion-sonarqube-scan-mode.html(.6 主動掃描) |
relates to FR-056(檢測工具平台/三表 schema)/ FR-057(connector 架構·SSH 型態·多檔回收·setup_guide)/ FR-039(Agent 心跳派工);吸收 Notion CM-953;來源本 session brainstorm |
| FR-059 | 2026-08-01 | 檢測工具 Profile / Content 庫(掃描設定檔後台管理)— 把掃描依據(profile / content)從「BE repo 版控+人工 rsync+migration seed 選項」四步人工鏈搬進後台管理:上傳(file)/ 登記(url)雙軌(P5,URL 憑證一概不管)、SYSTEM 公用版+TENANT 租戶自有雙軌(Category C 模式照抄 flow_templates)、version+is_current 單現行版(P4)、任務下拉動態化(param_schema 加 options_source: "profile_library" 宣告,FE 零改即可為未來工具接庫)、agent 動態拉檔+cache(/data/content/cache/<uid>/v<version>/,sha256 對帳)。即 Notion CM-992 範圍③「後台 content 管理機制」的立案,做完同時消掉封閉網路投放與私有版本庫憑證兩限制。第一期只做形態 A(inspec+gcb,P1);新表 config.detection_tool_profiles(D1,config schema RLS 有 tenant_detection_tool_configs 前例非首例);庫參照下發格式 profile:<uid> 顯式前綴、派工展開 _profile(D2);上傳收 zip / tar / tar.gz / tgz 四格式、50MB、tarfile+zipfile streaming 防 slip/bomb、agent 端統一解壓成目錄餵 cinc-auditor(D4 決策者修訂版);只驗結構+檔案安全、正確性由掃描結果反映(D8);8 支 TWGCB(file 型)+dev-sec 2 條(url 型)搬遷 seed 上線第一天下拉零回歸(P3/D7);舊路(bind mount+靜態 options)過渡一版退役(D5);agent 取檔復用 FR-058.7 通道、授權 resolver 分流 source_file / profile_ref 兩 claim(P2/D6,resolver 可插拔介面須在 058.7 開工前談定寫進其 T-7.1)。P1–P7 + D1–D10 共 17 項全拍板見 design.md §3。4 子需求 × 12 子任務:.1 BE 地基(表+RLS / API+守門 / 上傳驗證管線 / 搬遷 seed)→ .2 下發整合(宣告升版 / 派工展開 / profile_ref resolver)∥ .4 FE(管理頁 / 下拉動態化)→ .3 Agent 端(cache+拉檔+sha256 / 目錄交付 / 封閉網路驗證,硬依賴 058.7 通道)。Notion 開卡待 058.7 開卡完成後接續(避免 Case No 跳號)。討論稿 discussion.html |
relates to FR-058(母脈絡)/ FR-058.7(agent 取檔通道依賴,先行)/ FR-039(agent 安全基建與 sha256 信任根不變式);承接 Notion CM-992 範圍③ |
| FR-060 | 2026-08-03 | 檢測基準內容管理(Detection Profile Content Management)— 設計定案,待實作。FR-059 把 profile 檔搬進後台,但平台仍把它當不透明二進位檔,使用者在下拉只看得到一個名字:實跑 TWGCB-01-014 抽取得 234 條控制項,其中 199 條是 impact 0.0 人工待判項(執行時直接 skip)、真正自動檢查只有 35 條、覆蓋率 15%——使用者要等報告出來才知道,等於白等一輪掃描。三個需求:①瀏覽 profile 檢驗內容(核心,選擇「之前」就看得到要驗什麼)②修改基本資料含改名(現況改不動,名稱參與唯一索引,唯一改名途徑是 fork 複製)③分類體系(CINC 不只 OS 連瀏覽器都有,profile 一多下拉會選錯)。核心是主從拆表:detection_profiles 主檔(名稱/描述/分類三軸/scope/工具/is_active)+ detection_profile_versions 從檔(來源檔/sha256/version/is_current/supports/extraction_status)+ detection_profile_controls 控制項(一條一列,FR-061 豁免要能以外鍵綁單條控制項,這是最不可逆的決定)。現在是最便宜的時機——DEV 僅 13 筆(10 SYSTEM/3 TENANT)、FR-059 上線才兩天。D1–D19 全拍板見 design.md §3;D5 於 2026-08-03 二度裁示定案:分類 enum 存 DB 由 root 維護(推翻原「FE 寫死」建議),但多語不落庫——DB 只存 key、顯示由前端 i18n 翻譯不另開翻譯表,代價是新 key 未補前端翻譯前以原始 slug 顯示(優雅降級,須寫進 spec 免被誤認為 bug)。四項不可逆決策:D4 uid 由從檔逐列沿用(10 筆凍結契約 soft-ref 零轉換)/ D12+D19 controls 表跨格式形狀(正規欄最小集合+attributes jsonb+extraction_format·origin 雙標記,嚴重度欄不叫 impact 免第二個工具進來要改上線表)/ D2 is_current 布林+partial unique index(不用 FK 當唯一性保證,oscal.frameworks 走過該路且官方已認錯廢棄)/ D3 從檔自掛 RLS 冗餘欄(PostgreSQL 不沿外鍵繼承,file_id 洩漏搭 FR-058.7 取檔通道=實質檔案越權路徑;本專案首例主從雙表 RLS 無前例可抄)。🔴 兩處派工鏈破口(原以為零影響,實 grep 推翻):_load_profile() 的 is_active 守門拆表後在主檔,從檔 entity 有屬性但預設 None 則 None is False 為假 → 守門靜默失效、已停用 profile 照樣派得出去(無聲授權漏洞,比 500 更糟);_humanize_profile_param() 的 getattr(profile,"name",None) 有 default 不報錯,只讓通知信「掃描設定」靜默退化成 profile:<uuid> 且無任何測試會抓到——解法為 domain service 新增 get_version_with_profile(uid) 合成 entity。抽取落點=BE 主機裝 CINC Auditor(⚖️ 授權紅線 Apache 2.0,絕不可換官方 InSpec 6+ 商業 binary 或 inspec-core gem,均受 Chef EULA;275MB/三台部署機+每台開發機都要裝/路徑走 CINC_AUDITOR_CMD 比照 LibreOffice 慣例不硬編);抽取必非同步(234 條 28–29 秒/708 條 117 秒,遠超任何 HTTP 逾時),走 D19 抽取器註冊表骨架(依 profile_format 取 extractor,本期只實作 InSpec);失敗判定 exit != 0 或 controls == []——第七種錯誤形狀是 Ruby 語法錯導致 exit 0/stderr 全空/JSON 合法但零控制項,只看 exit code 會變無人察覺的資料缺漏。3 子需求:.1 資料模型(拆表+13 筆三段式搬遷+RLS 兩表八段+派工鏈破口修補,地基必先行)→ .2 分類與編輯(含 D5 改存 DB 新增的 enum 表/刪除保護/root 維護介面)∥ .3 抽取與瀏覽。🔴 遷移三大陷阱:搬遷 JOIN 必 (tool_id, tenant_id, name) 三欄(少一欄 id 32/33 會 cross join)/app_tenant_allowed_for_session(integer) 只接 integer 而 tenant_id 是 bigint → 八處都要 tenant_id::integer/id 33 搬遷後是 current_version_id IS NULL 的合法狀態(驗證預期 12 筆非 13)。環境紀律:開發期只套 DEV;STG 已服役(10 筆全 SYSTEM 無 TENANT)→ 🔴「STG 跑得順」不能當驗收依據(測不到租戶 RLS 路徑/32·33 三欄 JOIN 陷阱/孤兒主檔),驗收必須在 DEV;POC 等同 production,STG/POC 均需決策者當次明示放行。舊表只 rename 為 _deprecated_20260803 不 DROP(觀察期後另案)。討論稿 discussion.md |
relates to FR-059(profile 庫母脈絡,直接續作)/ FR-058(檢測工具平台·param_schema 宣告機制)/ FR-058.7(agent 取檔通道,RLS 越權路徑相關)/ FR-039(sha256 信任根);後續 FR-061(選用範圍/豁免/人工判定/自訂項,本案只定模型契約見 design.md §6) |
| FR-062 | 2026-08-08 | License 控管機制 — 設計定稿,待實作。Guidant AI 上線銷售前的授權地基:公司內部自建簽發端(獨立極簡 Flask 應用+CLI 共用同一 Ed25519 簽章引擎、獨立 repo 獨立 DB、部署內部不對外;不採 Keygen 等外部 license server)、產品端驗章執法(公鑰列表 kid 查表編譯進後端、時鐘回撥防護)、按功能模組授權(沿用 capability.resource_type,基礎包 21 模組+4 加值包,Plan 與分層皆為簽發端 plans 表資料非寫死)、可組態到期管線(notify 30 → grace 14 → readonly 終態、lockout 預設關,整組 expiry_policy 簽進照內、產品端零天數設定)、序號開通(離線先行/線上後續兩張 case)與機器指紋綁定、補發換綁、kid 金鑰輪替。照型態只有 formal / trial / extension(過渡照機制刪除,上線 migration 直接為既有租戶發正常照、執法第一天全量生效無特例分支);升級 Plan=換發新照立即生效;子租戶上限預設 5。執法走 common/authz 第六軸+唯讀 gate(全域攔寫入、登入/上傳照豁免)+任務型態與選單過濾+環境總開關;順帶補 api/grc/api/project 零守門技術債、退役 TENANT_ADMIN_EXCLUDED_RESOURCE_TYPES。D1–D15 全定案見 design.md §2;8 子需求(FR-062.1–.8)× 28 子任務見 design.md §5。2026-08-10 驗收回饋追加 FR-062.8:角色權限矩陣缺 license 維度(ui-routes 無授權標記/roles 寫入端零檢查/provisioning 未扣未授權模組),未購買模組的能力點看得到也勾得下去且真的入庫,採業界 show-and-disable(反灰+原因)、存量走 evaluate-time 抑制不刪權限資料(存量項最終定案為反灰空框、差異只留 tooltip,不用假勾勾表達),另含選單結構調整(/license/manage 改由 is_platform capability 表達平台專屬、取代 BE 與 FE 兩份硬編 url 清單;License 兩頁獨立為「授權管理」群組 sort=45;關閉未完成的自定義儀表板入口),× 5 子任務(T-8.1~T-8.5,Notion CM-1166~1171)。討論稿 discussion.md |
relates to FR-048(authz 五軸→六軸)/ FR-054(租戶生命週期·子租戶額度) |
| FR-054-2607-tenant-lifecycle-delegation | 2026-07-23 | 租戶生命週期與管理權下放(經銷商模式)— 五決策已拍板:①租戶 CRUD 全下放子樹管理員(限自己子樹;建 root 仍限 platform admin)②守門沿用 tenant.create/update/delete capability(拔 route 層 @require_platform_admin_route 硬門檻;DB RLS 已支援子樹判定不用動)③刪除改軟刪除(tenants 加 deleted_at;擋登入/選單過濾;空租戶保留硬刪;保留期清除排程後做)④同名策略=唯一性只算活租戶(partial unique:name WHERE deleted_at IS NULL;恢復時重新查重)⑤復原機制=獨立「已刪除」清單顯式 restore(絕不同名自動接舊資料,防跨客戶資料洩漏)+新增時善意提示;另含一條龍最後一哩:建租戶表單選填管理員 email → 自動 add_user 綁 System Manager 角色(寄密碼信)。涉 jedi-auth 套件異動(delete/查重/軟刪在套件內)。設計輸入補充(2026-07-24):①CM-860 遺留的硬刪 RLS+cascade 500 併入本 FR(軟刪上線即繞過,不另深查)②一條龍 provisioning 必 seed 部門+角色 × tenants FK RESTRICT → 每個正常租戶天生不可硬刪,「刪除」形同虛設——加重軟刪除優先度。尚未開工——等 user 下令走 brainstorm→design→plan;第一段緊急修(POST /tenant 下放)已由 Notion bug-loop 先行處理,見 Notion case 3a6346da-…-8056 | relates to FR-048(authz 五軸);來源 Notion case 3a6346da-4cd0-8056 |
| FR-063-2608-nuitka-packaging | 2026-08-14 | 落地版程式碼保護:Nuitka 編譯打包(Linux 容器版)— 三階段戰線第一段(FR-063 編譯 → FR-064 防竄改 → FR-065 Installer)。採 Nuitka standalone 編譯為機器碼 binary 包成 Linux Docker image 交付(取代 .pyc 方案),本階段只做 Linux 容器版、另開 production Dockerfile(現有 Dockerfile 為 E2E 專用不可疊改)。2026-08-13 STG 實測:冷 build 1h27m / 產物 808MB,import 期炸 dependency_injector(Cython 與 Nuitka 靜態環境不相容)。清障項:私房 wheel(CYTHON_PEP489_MULTI_PHASE_INIT=0)、DI auto-scan 改 build 期靜態模組清單、eventlet/WeasyPrint 逐雷排除。Notion CM-1187。設計定案 2026-08-14,見 design.md |
relates to FR-062(License Center) |
| FR-064-2608-tamper-detection | 2026-08-14 | 落地版程式碼保護:防竄改偵測與授權鎖定 — 三階段第二段,依賴 FR-063 產物。Build 期逐檔 SHA-256 manifest 以原廠私鑰簽章(復用 FR-062 License Center 簽發體系,不另建 PKI);啟動驗章+逐檔比對與 license 驗證共用同一 code path;runtime APScheduler 低頻抽查;偵測竄改 → tamper 雙落點 + exit + 之後啟動一律拒絕,唯一解鎖路徑=原廠一次性 unlock token。已知限制已對齊:目標是拉高成本 + 留蓄意痕跡,B2B 法律層是真實防線。Notion CM-1188。設計定案 2026-08-15,見 design.md |
relates to FR-062(License Center)/ FR-063(編譯產物) |
| FR-065-2608-onprem-installer | 2026-08-14 | 落地版 Installer(安裝器與交付流程)— 三階段第三段,依賴 FR-063(image 產物)與 FR-064(簽章/license 機制)。目標:客戶端落地安裝標準化,不依賴原廠工程師手動部署。2026-08-16 設計定案(D1–D12,餘 D11.3/D11.5/D13 開放):full-stack compose(PG/Redis 全包+FE production image nginx 同源反代)、docker save bundle+digest 驗證、分段 SQL+one-shot init 容器建庫、純 bash install.sh+Web 設定精靈(setup token+建 admin+指紋展示+license 匯入)、--upgrade 四步與回滾、PROD 簽章鑰、K8s 預留;Windows 僅出評估文件。見 design.md。Notion CM-1189 |
relates to FR-063(image 產物)/ FR-064(簽章機制) |
| FR-066 | 2026-08-18 | 檢測 Agent 原生安裝包 — 把檢測 Agent(evidence-agent)從 docker 三容器出貨改為 Nuitka 編譯+外部工具全包的一顆 tarball,install.sh 一鍵安裝為 Linux systemd 服務。動機:agent 本職是量測宿主機,指紋(product_uuid / machine-id / MAC)容器內讀不到或會漂移,業界同類(Nessus/Qualys/Wazuh)皆原生交付。D1–D9 全拍板:D1 Nuitka standalone→tarball→systemd(排除 onefile);D2 agent-db(postgres:16)退役換 SQLite(僅 jedi-file-upload 一張表);D3 外部工具全包一顆(CINC ~275MB/sonar-scanner+JRE/LibreOffice+fonts-noto-cjk/xsltproc/git,~1GB+ 已接受,封閉網路完全自足;ZAP/OpenVAS/OpenSCAP/Nmap 引擎不 bundle);D4 agent 自起 TLS 8443 砍 nginx sidecar;D5 systemd EnvironmentFile+互動問答三題、客戶側 mTLS 全自動零 openssl;D6 build 期 manifest 簽章+啟動驗章(複用 FR-064 泛用層加 agent_manifest type,不做 runtime 全家桶);D7 升級回滾=versions/ 目錄+symlink 切換(無 pg_dump 備份模型);D8 Windows 只出評估文件;D9 指紋 Linux 原生直讀、廢 collect-host-id.sh、不預抽 OS 抽象層。開放查證 Q1–Q4(LibreOffice 離線化形式/PG 方言掃描/EXCLUDE 名單重評/openscap-utils 殘留)。4 子需求 × 11 子任務串行:.1 Nuitka build 管線與程式改造(SQLite 化/version bake/resource_path/指紋直讀)→ .2 tarball 打包+工具 bundle+簽章 → .3 install.sh 七步+systemd+upgrade/rollback+維運子命令 → .4 乾淨機真機+封閉網路驗收+客戶手冊+Windows 評估。標的 repo:evidence-agent。見 design.md、討論稿 discussion.html |
relates to FR-063(Nuitka build 管線)/ FR-064(簽章泛用層)/ FR-065(install.sh 結構)/ FR-039(evidence-agent 本體) |
| FR-067 | 2026-08-23 | 檢測多 Agent 分派(Detection Multi-Agent Dispatch)— 設計定案,待拆卡。檢測任務可設定多組「哪台 agent 掃哪些目標」(assignment),一次執行展開 N 張工單同時派給多台、各掃自己的網段,全部回報完才算完成,報告與通知彙總呈現。動機:現況 _pick_agent 挑機無序且不驗在線(挑中離線機工單永遠 pending 卡死),客戶多網段環境(辦公網/機房網/DMZ 各一台 agent)無處指定「這批目標給哪台」。D1–D9 全拍板(2026-08-23):D1 模型 B(展開 N 筆 detection_executions 維持與 agent_tasks 1:1,上加 detection_execution_groups 彙總層——1:1 是回報鏈/報告反查/FE 渲染的大量隱含依賴,原地保留);D2 assignment 存新子表 job_execution_detection_tool_agents(每列有 uid 可單列 CRUD/按列稽核/兩入口併發不互蓋,支撐未來中心 UI 與我的任務頁調整兩場景;排除 tool_params JSONB 內陣列——無列身分且會整份快照進 agent_tasks.params 漏到執行紀錄);D3 執行前逐台驗證(存在/enabled/未 revoke/有能力/在線)任一不過整次 400 列全部不合格機;D4 彙總=全成 succeeded/任一敗無跑 partial_failed/全敗 failed/cancelled 比照 failed;D5 auto 完成=group 全 succeeded 才 complete_job(partial 留人工),順修「多筆各觸發撞 409→agent 收 5xx」地雷(收口 group 列鎖);D6 通知改 group 收口一封彙總(每 assignment 一列);D7 整組啟動+單組重跑+單組/整組取消(user 修訂比討論稿多單組操作;重跑=同 group 追加新 execution、彙總以每 assignment 最新一筆計;單組首次啟動第一版不做);D8 不做存量 backfill(開發階段資料會重置;無 assignment 時 fallback 自動挑一台健康的保留);D9 四項地基併入(remote-agents 補 capabilities+在線+過濾/執行紀錄 enrich agent 名/test_connection 對齊/_pick_agent 濾離線)。Agent 端(evidence-agent)零改動。6 子需求 × 14 子任務:.1 地基 ∥ .2 資料層 → .3 綁定設置 / .4 展開收口 → .5 彙總呈現與通知 → .6 收尾。見 design.md、討論稿 discussion.md |
relates to FR-056(檢測工具平台)/ FR-058(檢測執行/工單模型)/ FR-039(evidence-agent 心跳領單) |
| FR-068 | 2026-08-25 | 系統 Log 轉發(Log Forwarding)— 已上線(v1.17.0)。系統 log 可於 UI 設定轉發到客戶自有 log server(ELK/Graylog/rsyslog)。D1–D6 拍板(2026-08-25):D1 協定 Syslog(RFC 5424,UDP/TCP)+GELF 兩種(三家最大公約數;排除各家專屬 API);D2 範圍=應用 log+稽核事件兩流分開勾選(合規客戶接 SIEM 要的是稽核事件);D3 系統層全域一份、表帶可空 tenant_id 預留租戶層;D4 轉發失敗不拖垮主服務(QueueHandler 旁路+靜默降級);D5 第一版不過濾敏感內容、預留遮罩 pipeline 掛點與 UI 開關位;D6 熱生效+測試按鈕。agent log 轉發本案不做(未來另案)。3 子任務:T-1 BE(表+CRUD+handler 鏈)→ T-2 FE 設定頁 → T-3 手冊三家對接範例,另 T-4/T-5 出版與 188/189 升級、四筆修正(syslog 不合 RFC 5424/license 誤標未授權/遮罩開關隱藏)皆已 Done。見 站台索引、design.md |
relates to 稽核事件埋點(reference_audit_event_logging_pattern)/ FR-065(落地版場景) |
| FR-069 | 2026-08-29 | 主專案功能模組化——jedi-* 套件抽取計畫 — 設計定案,待拆卡。把可通用功能抽成 jedi-* 外部套件供未來產品複用。三棒平行盤點定調:40 模組/1500+ 檔中,核心不可分割環(participant↔︎flow_engine↔︎grc↔︎associations↔︎oscal↔︎module_frame ≈760 檔)不切片,外圍葉節點逐支抽出。D1–D4 拍板(2026-08-29):D1 第一階段收 P0–P5 + P7–P8 共 8 arc(P0 前置清理:合併 uploadfile 雙模組/斷 common/ 9 條反向 import/error code 歸位 → P1 jedi-ai-bot 練手 → P2 jedi-integrity(FR-064 成果)→ P3 jedi-log-forwarding(FR-068 成果)→ P4 jedi-remote-agent(含 agent_auth mTLS)→ P5 jedi-license-runtime(INotifier port)→ P7 jedi-common 擴充(response_util 124 處上移,全量回歸)→ P8 authz 主體域併 jedi-auth);ai-dashboard 降觀望(無確定消費者);D2 核心抽取 P9–P13 凍結進路線圖(jedi-detection / evidence-classification / task-survey / jedi-participant(解環鑰匙:最大 hub 但 out-degree 僅 8) / oscal 三角拆解),等 P0–P8 收口拿實際成本數據再議,出現第二消費者可單獨解凍 P9;D3 authz 拆兩半——主體域(platform/admin/capability/decorators/signed_token)併 jedi-auth、資源域(project/ssp/workflow/menu_license_filter)留主專案(排除獨立 jedi-authz:生依賴邊且無單獨消費場景);D4 抽取配方沿用 jedi-information-system(FR-032 G)範本:import 名不變/窄 ABC port/套件不含 api 層與 migration/extract→publish→pin 順序/守衛測試。見 design.md |
relates to FR-032 G(jedi-information-system 抽取先例)/ FR-064(integrity)/ FR-068(log_forwarding)/ FR-048(authz 統一守門)/ FR-062(License Center) |
| FR-070 | 2026-09-02 | AI/Google Drive 憑證 DB 化與功能開通 — Phase 0 白話需求。AI 供應商金鑰(Anthropic/OpenAI)與 Google Drive OAuth 憑證從環境變數改存 system_configs(加密落庫,照 DETECTION_TOOL/DRIVE_TOKEN 加密先例)+系統設定頁 UI 開通(遮罩顯示);設定權限限 admin tenant(軸① require_platform_admin);服務端讀取 DB 優先 env fallback;key 從此不進出貨物(image/安裝包/guidant.env)。緣起:FR-069 收整期調查發現落地版無 key 進場機制。見 requirement-draft.md | relates to FR-069(調查緣起)/ FR-065(installer/guidant.env)/ 設定 schema 申報制(FR-069 記帳) |
| FR-071 | 2026-09-02 | 客戶端診斷包與錯誤收集站 — 🟡 設計定案待開卡(2026-09-18,D1–D11 全數拍板、4 子需求 23 子任務)。落地版裝在客戶機房,出錯時案發現場全留在那邊,目前唯一動線是派人到場。四棒補齊:①log 地基(出貨環境明訂 RUN_ENV、log 檔改按天輪轉保留 30 天、每筆 log/存取紀錄/錯誤事件帶同一條追蹤編號 req-<8 hex>、5xx 補「誰打了哪支送了什麼」一行 JSON、存取紀錄等級依狀態碼標 ERROR、DBLogHandler 加 filter 把除錯 log 擋在 DB 外);②GlitchTip 進出貨包(MIT 授權、每客戶一套、自帶 DB 與 Redis、開放註冊預設關、映像進 build_bundle.sh);③guidant diag 指令產包(環境快照/log 切片/DB 診斷切片/錯誤事件/manifest,遮罩管線共用 masking.py、上限 100MB 砍最舊且截斷要寫進 manifest、不加密);④支援頁(最近 ERROR 列表+一鍵匯出,平台管理員限定、守門下沉 service 層;另補操作日誌時間區間查詢——現況匯出端點不吃參數=全量倒出)。驗收條款寫死:故意弄壞一個功能→產包→丟給乾淨 AI 對話(只給包+原始碼)→ 要能指出根因與修法,過不了不算完成。🔴 推翻討論稿的錯誤前提:出貨端根本沒設 RUN_ENV,預設值讓客戶機房跑的是 dev 那套(檔案與 DB 輸出都開著),不是「落地版沒有 log 檔」;STG system_logs 實查 586,498 筆當天仍在寫,稽核事件與除錯垃圾比 467 : 586,031,D3 因此從「退役整張表」改判為「表留著、寫入端加 filter + 清舊資料」。前作 FR-071.0 錯誤追蹤試用已完成(母卡 CM-1906)。見 design、discussion、requirement-draft |
relates to FR-065(guidant CLI/installer)/ FR-068(log 轉發鏈,改 log 設定有打破風險)/ FR-064(授權狀態與金鑰遮罩)/ FR-063(commit hash 取得路徑)/ FR-110・FR-107(守門與選單 migration 先例) |
| FR-072 | 2026-09-02 | Console 安裝教學影片套件 — ✅ 全案收口(2026-09-03,母卡 CM-1517+12 子卡全 Done):六支+完整版交付於 test repo reports/training-videos/GuidantAI-落地版安裝教學-v1.19/(影片④已以 Agent 1.0.0 重錄),C 段 @install-test gate 已接線(npm run install:test)但未實跑——正式當 gate 前先小範圍試跑(scripts/build/README.md 已標);SUMMARY 見 handoff/2026-09-03-B-SUMMARY.md。落地版安裝流程(系統需求/主產品安裝/License 申請匯入/Agent 安裝/首次登入)的 console 教學影片管線:ttyd 把 terminal 變網頁+Playwright 錄影,既有 training 套件(Cucumber + overlay 字幕)零改動繼承,唯一能 web + console 混排的方案(D1);spike 已驗證全鏈可行(2026-09-02),畫面文字走 window.term xterm buffer API 讀取(canvas 渲染 DOM 讀不到)。D1–D6 拍板:BDD 同軌不另起爐灶(D2)、5 檢查點分段錄製 clean→bundle-uploaded→installed→licensed→agent-ready(D3,190 全清為起點)、敏感內容三層防線(分鏡禁 cat 敏感值→overlay 遮罩→ffmpeg 打碼,D4)、同組 feature 加 @install-test 模式掛出包驗收當 release gate(D5,呼應 T-6.6 乾淨機實裝教訓)、文件 canonical 在 test repo(D6)。3 子需求 × 11 子任務:A 錄影基礎設施 → B 五支影片+合併 → C 自動化安裝測試;B3 依賴 license 流程文件定稿。見 design.md |
relates to FR-065(installer/install.sh)/ FR-062·064(License 流程)/ FR-066(Agent 安裝包);實作落點 test repo training 套件 |
| FR-073 | 2026-09-03 | 檢測 Agent 安裝形態比照主產品 — 已實作+190 四路徑實機驗收通過(agent 1.0.0 已出包)。現況 agent 包「解壓目錄=安裝目錄」(.env/憑證/compose 全留家目錄,完成畫面要印「請勿刪除」);改為固定 /srv/guidant-agent+/etc/guidant-agent/install.conf+CLI 指固定路徑,解壓目錄用完可刪。D1 落點 /srv/guidant-ai-agent(同族 /srv/guidant-ai,且與 image 名 guidant-ai-agent 對齊;連帶避開原生版已佔用的 /etc/guidant-agent)/D2 複製不 symlink/D3 compose 釘 name: guidant-ai-agent+volume 名固定+三態判定(全新/已新形態=升級語意/舊形態=自動遷移搬 volume)/D4 補「容器實際 image tag == 要裝的 tag」斷言/D7 版號 1.0.0(脫離 0.x,準備發佈;初版 design 寫 0.3.0 是誤判——該 repo 版號史一路 0.2.x patch,中間位從沒動過)/D8 安裝 log 移到 /var/log/guidant-ai-agent/(FHS+活過 uninstall,主產品那套會被自己的 uninstall 刪掉)。鐵證:CM-1533 換版新目錄首裝撞固定 container_name 靜默失敗+憑證消失 409;實查 188 的 install.conf 更指向 /tmp(重開機即失聯)。實查目前無外部客戶安裝。見 design.md、requirement-draft.md |
relates to FR-072(錄影片④實測起因;影片④需重錄,由 FR-072 原 session 處理)/ FR-065(主產品 installer 範本)/ FR-039(agent) |
| FR-074 | 2026-09-03 | 檢測工具整合教學影片系列(Act 04)— ✅ 2026-09-04 收口,六章 28 段 75:42 交付(test repo reports/training-videos/GuidantAI-檢測工具整合教學-v1.19/,母卡 CM-1535+7 子卡;實作擴為七支工具全設定全執行,偏離/坑/follow-up 見 handoff/2026-09-04-FR-074-SUMMARY.md)。原案:用既有 test repo training 錄影管線(Cucumber + Playwright + overlay 字卡)產出 Act 04「檢測工具整合」六章 13 段教學影片(~30 min):04-00 總開場/04-01 檢測工具管理(OpenVAS API 型+OpenSCAP SSH 型、測試連線、部署前提、停用/重置金鑰)/04-02 掃描設定檔管理(公用版 vs 自有、上傳版更、控制項清單、複製到他工具)/04-03 任務設為檢測工具執行(PM 視角,OpenSCAP+GCB 兩任務對照完成模式)/04-04 執行與結果回收(執行者→PM,開始執行切點等掃描、報告變證據、重跑取消)/04-05 總結。D1–D5 拍板:190 安裝版+亮色 UI_THEME=light 錄製(D1)、六章 13 段每段獨立 scenario(D2)、分段錄製合併(D3)、敏感值三層(私鑰欄位 CSS 遮罩→後製馬賽克→feature 禁真值,D4)、7 子卡拆棒 S0 地基 Opus+五章 Sonnet 5+首腦收口、劇本與製片同一棒(D5)。見 design.md;分段腳本在 test repo training/chapters/04-detection-tools/ |
relates to FR-056/057/059(影片內容來源)/FR-072(同期 console 影片管線,本案純 web 錄影不依賴);實作落點 test repo training 套件 |
| FR-075 | 2026-09-05 | jedi-* 套件安全掃描與修正 — 掃描重做中,六棒已開卡待派(母卡 CM-1546+CM-1547~1552)。用 Claude Code claude-security plugin 掃自家 25 支 jedi-* 套件(過去 security-scan-2607 只掃主專案 BE/FE,套件從未做過系統性掃描)。第一輪試掃不完整:40 個 agent 只有 28 個回報、驗證面板從未執行,找到 19 條(7 條 HIGH 逐條開檔核對屬實:OpenLDAP 匿名 bind 從不驗密碼/LDAP filter injection/TLS 不驗憑證/Google 不驗憑證即發 session/任何人可綁外部身分到他人帳號/OTP 端點無認證無限次可換 JWT;MEDIUM 含 RLS fail-open 三條同根因),但覆蓋率無法宣稱,屬下限非全貌。重做方式:jedi-iam 切六棒按攻擊面而非目錄大小(S1 認證 11 檔/S2 授權守門 8 檔/S3 第二因子 34 檔/S4 API 邊界 24 檔/S5 應用領域服務 67 檔/S6 資料存取共用工具 69 檔),每棒獨立跑完整條含面板,effort 一律 low、model 用 Sonnet 5。成本教訓:medium 展開成矩陣派 40+ agent 且無共用 context(同檔被 8 個 researcher 各讀一遍),兩次都因額度耗盡零產出。見 scan-findings-batch1.md、scan-methodology.md |
relates to security-scan-2607(前次掃描,範圍不含套件)/CLAUDE.md 外部套件異動規範 【2026-09-11 更新】S7 重跑完成並驗收:第一輪 74 檔因研究員越界重複 S1 而作廢,重跑收窄成 29 檔(middleware/common/ports/auth_provider/plugin.py/security_policy.py,明寫排除 S1 已掃路徑),4 條候選零越界——證明「卡片明寫不要讀哪些路徑」是有效做法。結果 1 條 MEDIUM(3/3 通過):員工被停權後手上憑證仍可用約三天半、自己可續到約八天——停權只改一個欄位不收回憑證,認人時只判 user is None 不看 status,資料層 status >= -1 而 REVOKE 正是 -1,續期那支更是全程不查使用者;修法要同時改兩處。人工另查出 plugin.py:191 忘記密碼遮罩預設為關(LOW)與自動產生密碼少一個字元(非資安 bug)。⚠️ 派 2 研究員只回 1(另一個 stalled 重試六次未救回),「只有這一條」不可宣稱。runner 未交付報告,首腦補寫。 |
| FR-076 | 2026-09-06 | License 簽發與驗證鏈資安掃描 — 四棒已開卡待派(母卡 CM-1566+子卡 CM-1567~1569、CM-1571)。掃 license_center(簽照端,私鑰所在)與 jedi-license-runtime(主產品內的驗照端),兩端從未被系統性掃過——security-scan-2607 只掃主專案 BE/FE、FR-075 掃 jedi-common/jedi-iam,License 鏈是完全空白。比 jedi-iam 更值得掃:繞過授權=免費使用整套產品,攻擊者動機直接。首腦讀碼後標出的重點面:verify_payload 同收 v2 信封與 v1 明文兩種格式(降級攻擊空間)/license·manifest·unlock_token 三種憑證共用一支驗章與同組公鑰且 payload_type 缺鍵預設當 license(型別混淆)/公鑰硬編 DEV·STG·POC 三把(DEV 私鑰簽的照 POC 也認)/機器指紋讀不到 machine-id 就退回 MAC(FR-064 踩過容器空檔漂移)/runtime 端點自己不掛守門靠宿主注入(有無漏掛)/license_center 是對外網頁後台(登入·CSRF·模板注入·API token,性質與其他棒不同)。四棒:L1 驗章核心 10 檔(優先,密度最高兼驗證 Opus 1M 組合)/L2 授權狀態與 API 33 檔/L3 簽發核心與模組 32 檔/L4 網頁後台 43 檔。共同設定沿用 FR-075 教訓:主 session 一律 Opus 5 1M(Sonnet 跑 40 檔以上必被 180 秒 stall 門檻砍)、effort low、focus attack-surface、每棒 40 檔內、看 stamp 的 verification 欄確認面板跑完。私鑰紀律:keys/private.pem 在工作目錄內 agent 讀得到,任何情況不可把金鑰材料寫進報告或落地檔。見 README |
relates to FR-075(掃描方法與成本教訓)/FR-062(License 設計)/FR-064(manifest·unlock_token 共用驗章) |
| FR-077 | 2026-09-07 | 遠端 Agent 控制鏈資安掃描 — ⏸ 決策者 2026-09-08 裁定暫停,改從其他 jedi- 套件開始掃(第一支 jedi-notification,見 FR-078)。已完成:R1「agent 身分與註冊」42 檔掃完並經首腦驗收,7 條發現(1 CRITICAL/2 HIGH/3 MEDIUM/1 LOW 越界)——根因是控制面四端點(register/heartbeat/ack/result)完全不掛認證,程式碼註解說身分靠上游 nginx 的 mTLS 終結,但出貨的三份 nginx 設定 grep 不到一行 ssl_verify_client,於是 agent 身分只剩「請求自報」;F1 心跳無認證即取走該租戶掃描工具的明文帳密(客戶自己的 SonarQube token/SSH/WinRM,經決策者升 CRITICAL)、F3 同根因可跨租戶、F2/F5 ack/result 不查任務歸屬可偽造或抹除稽核證據、F4 健康檢查 SSRF、F6 enroll token 全租戶共用且永久有效可搶接他人 agent、F7 jedi-common/.env 受版控(越界)。未完成且隨 arc 暫停*:修正卡 4 張(CM-1595 CRITICAL 併 F1+F2+F3+F5+nginx 連帶/CM-1596 SSRF/CM-1597 enroll token/CM-1598 .env)與補掃 1 棒(CM-1599 密碼學核心 10 檔),加上 R2a 18 檔/R2b 13 檔/R3 17 檔三棒——卡都開好、範圍寫死、隨時可續。暫停理由:R1 的驗證面板因額度用盡全滅(105 個 verifier 一個沒活、21 票 0 投),工具正式產出是空的、覆蓋率無法宣稱,靠人工逐條開檔補核才有東西;那 7 條本身經 runner 逐條核行號+首腦複核關鍵條,依據紮實可拿來當修正依據,不可信的是「只有這七條」。與其在同一大套件反覆試工具極限,先換範圍天然較小的套件重取可信跑次。首腦建議 CM-1595 是 CRITICAL、不該跟著 arc 一起停。見 README、scan-R1-agent-identity.md |
relates to FR-075/076(掃描方法與成本教訓)/FR-078(接續的下一輪掃描)/FR-039(agent 分散式檔案)/FR-058.7(檔案下載授權)/FR-066(agent 身分模型 v3、指紋二源化)/FR-069(套件化插件契約) |
| FR-078 | 2026-09-08 | 通知投遞(jedi-notification)資安掃描 — 已開卡待派(母卡 CM-1602+子卡 CM-1603 N1/CM-1604 N2)。掃 jedi-notification 這支通知投遞套件與它在主專案的宿主接線:它掌管產品所有對外通知(SMTP 寄信、Discord webhook、Telegram bot),三條管道的共同特徵是都要存客戶填的機密、都要主動對外連線,故風險集中在「機密怎麼被讀出來」與「被騙去連別的地方/連不上就吊死」。選它的理由:決策者 2026-09-08 裁 FR-077 暫停改掃其他套件,這是第一支;它是「真的獨立」的套件(與其他 jedi-* 耦合少,範圍守得住);是至今嘗試過最小的一棒——攻擊面口徑只有 30 檔 1,011 行,扣掉 15 個空的或幾行的 __init__.py 後真正有邏輯的僅 15 檔 622 行,比 FR-076 L1(10 檔,唯一一次面板完整跑完的紀錄)略大。N1 同時是額度可行性實驗:決策者目前在 5X token 額度,這一棒要回答「工具在此額度下還能不能把驗證面板跑完」,故 N2 不平行派、等 N1 驗收完才派。首腦讀碼後標出的重點面——套件側:smtp_mail_adapter.py 的 starttls() 不帶 SSL context 等於不驗憑證(與已修的 LDAP TLS CM-1560/Redis TLS CM-1565 同一類病,第三處)/同檔 except 把整個 config 物件(內含明文密碼)印進 log 且正常路徑也印帳號伺服器/Telegram 與 Discord 的 requests.post 完全沒 timeout 會吊死 worker(SMTP 那邊有設 60 秒,同套件內做法不一致)/收件人與主旨直接組進郵件標頭而測試信端點的 to 使用者可控(CRLF 標頭注入面)/Discord webhook 是使用者填的任意 URL 伺服器照打(SSRF,同 FR-077 F4 形狀)且 Telegram bot token 拼在 URL 路徑(會進 log)/notification_factory.register_adapter 無條件覆寫且 docstring 自稱刻意(工具已知盲點「會被註解說服」的典型,驗收要確認 runner 有獨立結論)/非資安但要記:MailRequestDTO 的 cc/bcc/attachment 三欄 adapter 完全沒用、靜默丟掉。宿主側:test_mail_service.send_test_mail 在使用者沒改密碼時會從 DB 讀既存 SMTP 密碼合併進使用者送來的設定再試寄,持 smtp-config.update 能力點者送一個指向自己伺服器的 host 就能收到平台明文密碼(LDAP 同款已在 CM-1564 修過,SMTP 看來沒修)/notify_config_test_service._resolve_value 是 Discord/Telegram secret 的同款模式/十多個消費點有多處在背景 thread 呼叫寄信(無 user context 時 get_channel_config 有防護但 get_notifier 走繞 RLS 的 read_root_config_value,要確認 fail closed)/system_config_root_reader.py 整支繞 RLS 直讀且是 SMTP 設定的真相來源。版本落差鐵則:主專案 pin jedi-notification==0.0.11 且 path override 是註解掉的,掃的是 monorepo HEAD 可能領先部署版,每條發現都必須註明「在 0.0.11 是否同樣存在」,否則修正卡對不上部署中的版本。兩棒:N1 套件本體 30 檔(jedi monorepo)/N2 宿主接線 8-10 檔(BE repo:test_mail_service、notify_config_test_service、宿主 notification_service、notify_config route 與 serializer、notification_plugin_wiring、system_config_root_reader、DI container)。分兩棒因為 scanRoot 只能指一個目錄,且風險活在套件與宿主的接縫上——套件把「設定從哪讀/密碼怎麼還原/誰能呼叫」全外包給宿主,單看任一邊都看不出問題,驗收時首腦必須把兩份報告放在一起對。共同設定沿用前三個 arc 教訓:主 session Opus 5 1M、effort low、focus attack-surface、啟動前驗 scope 檔數、看 stamp 的 verification 欄確認面板跑完。見 README |
relates to FR-075/076/077(掃描方法、成本教訓與暫停裁決)/FR-020(notify-config 原始需求) |
| FR-079 | 2026-09-08 | 公告(jedi-bulletin)資安掃描 — ✅ 兩棒皆掃完並經首腦驗收(2026-09-09)(母卡 CM-1609+子卡 CM-1610 B2/CM-1611 B1)。結果:B1 套件本體工具零發現(2 候選皆 0/3 否決,面板完整);B2 宿主接線 10 條(8 MEDIUM/2 LOW,十條全 3/3 全票、verified、unreviewed_candidate_sites: 0,過程撞兩次額度後以 resumeFromRunId 續跑補齊),無 HIGH 以上。範圍內四條全在 app/bulletin/service/bulletin_service.py:F13 AI 儀表板旁路(不經 route 守門+呼叫端寫死 params={} 使部門過濾永不生效 → 任何登入者可讀全租戶公告含草稿,前三筆原文送第三方 LLM,本棒最重要)/F16 改刪只驗 capability 不驗歸屬(delete_bulletin(uid) 連 user 都沒收,連帶無條件清空部門關聯)/F17 單筆讀取無範圍檢查(依 B1 查證 uuid4 降 LOW)/F18 列表對無部門帳號直接放行。兩項查證:bulletin.read 能力點存在、綁在 route、寫進設計文件,但全 Python 程式碼一次都沒檢查它——坐實是漏守門不是設計如此(與 CM-1585/CM-1589 同型);bulletin_org_units 整張表零 RLS 零 policy。決策者親裁兩條:F12(JWT 金鑰散在版控 31 檔)經查 install.sh:1252 每套安裝各自 openssl rand -base64 32、外流的只是開發機那把,降衛生類併 CM-1607、DEV 不換金鑰(首腦原主張升 HIGH 作廢);F15(installer 每套種同一組原廠 super admin 密碼)維持記錄暫不調整。修正卡 A/B 兩張待建,依既有裁定先不派、由 PM 統一安排。 換到的方法論:判密鑰外洩的嚴重度第一問是「客戶端用的是不是同一把」而非「這把是不是活的」;續跑後必須核對併檔的條數與標題(save_result.py 遇同 shard 會靜默擇一、不報錯)。掃「公告」這條鏈:管理員發公告、指定發給哪些部門,其他人在自己畫面上看到——要回答的是有沒有人能看到不該看的公告、改別人的公告、或發公告給不屬於自己的部門。選它的理由:排名表把 jedi-bulletin 列在「讀取展示型、攻擊面小」那組(29 檔/847 行),但那個評估只看了套件那半邊;首腦這次讀完程式碼發現套件本體確實只有無守門的 CRUD,而「誰能看到哪一則公告」的判定整個在主專案宿主接線裡,且邏輯出乎意料地繞——是一條被低估的鏈。兩棒:B2 宿主接線 33 檔(BE repo,api/app/domain/infra/di_containers 五處+dashboard 註冊檔)/B1 套件本體 29 檔(jedi monorepo 的 jedi-bulletin/)。分兩棒的唯一理由是 scanRoot 只能指一個目錄,檔數各自都在 30 檔尺內;建議先跑 B2——首腦標出的十個重點有八個落在那半邊。首腦讀碼後標出的重點面(全部未經驗證,是研究員的思考起點)——宿主側:五條 route 裡寫入三條都掛了 @require_capability、兩條讀取(列表與單筆)只有 @jwt_required()(與已修的 CM-1585/CM-1589「讀取端漏 .read 守門」同形狀,本專案已知會重犯的病)/get_bulletin(uid) 只吃一個 uid,不看部門、不看建立者、不看 enable、不看發布與過期時間,列表那條費心做的部門過濾在這條路上完全繞過/列表的部門過濾是反直覺 if-else 且開關 auth 是呼叫端在 request body 自己傳的布林值,else 分支對「沒有部門的使用者」註解明寫「不過濾、顯示全部公告」/兩支 repo impl 的 _gen_filters() 都在 query_entity.__dict__ 上跑迴圈用 hasattr(model, field) 當白名單,而主專案的 BulletinQueryEntity.__init__ 收 <strong>kwargs、serializer 是 apply=False 手動 load(呼叫端的鍵能不能變成查詢條件要實查**)/update_bulletin 與 delete_bulletin 只驗 capability 不驗歸屬,跨租戶最終只靠 RLS 擋而 bulletins 表的 RLS 現況未經查證(migration 註解已明指其 INSERT policy 與其餘三支不對稱)/update_bulletin 第 165 行無條件先刪光部門關聯再重建,沒帶 org_units 的部分更新會清空可見範圍(CM-1588 同類,該案已確認為真)/content 是完全不驗證的 fields.Raw() 寫入讀出原樣進出、DB 無長度上限,FE 渲染方式要實查(公告是「發給很多人看」的內容,XSS 受害面比一般欄位大)/di_containers/dashboard_apis/bulletin.py 把 get_bulletins 註冊給 AI 儀表板呼叫,是一條不經 route 層守門的旁路/審計欄位 created_user_name 用跨到 users 表的 scalar_subquery 實作、同時又是可被呼叫端傳入的查詢欄位。套件側:模組最後一行有個 import 時就實例化的模組層級單例(CLAUDE.md 的 lazy session 鐵則相關)/五個方法各自 new 一份 repo 繞過注入/update() 第 53 行檢查了參數而非查詢結果(查無此筆會 AttributeError)/generate_uuid 的實作要人工看一眼——公告 uid 若不是密碼學等級隨機,那條無守門的單筆讀取影響就放大(跨棒依賴:這一條直接影響 B2 重點 ② 的嚴重度判定)。特別警告寫進 B1 卡:plugin.py 檔頭有 60 行極詳盡的自我辯護文字(自稱零跨套件 import、零 os.getenv),正是工具已知盲點「會被程式碼註解說服」的高危形狀(FR-075 的 S2 就是八檔零發現卻漏掉真洞),驗收要確認 runner 有獨立結論。共同設定沿用前四個 arc:主 session Opus 5 1M、effort low、focus attack-surface(附帶密鑰專項,FR-078 六條裡四條由它掃出)、每棒 ≤30 檔、啟動前驗 scope 檔數、看 stamp 的 verification 欄確認面板跑完;runner 不啟動掃描(disable-model-invocation,指令交決策者親手打)。見 README |
relates to FR-075/076/077/078(掃描方法、成本教訓與暫停裁決) |
| FR-080 | 2026-09-09 | jedi-* 套件整併與服務化路線(插件化第一階段)— ✅ 已收口(2026-09-12):八棒+六張插隊卡+review 衍生九張修正卡全 Done、首腦親驗,2026-09-11 併入 feature/FR-075;發版/pin/SPEC/release note 歸 FR-089。25→21 支(asset/system-core/log/task-platform 四組合併、bulletin 補實、六支殼進 archive);跨套件 import 120→105、零使用接口 16→6。驗收抓到並修掉:出貨基線缺六項結構、主專案讀被拆 ORM 屬性、檢測任務顯示成一般、切租戶權限全空(users RLS 本人例外)。露出租戶隔離破洞(projects/job_executions RLS 關著、待辦 view 繞 RLS)→ 歸 FR-075 資安 arc,切子租戶暫不對外。接手讀 handoff/fr080-to-fr075-HANDOFF.md |
|
| FR-081 | 2026-09-09 | 問題追蹤(jedi-issue)資安掃描 — ✅ 六棒全數掃完並經首腦驗收(2026-09-10)。面板六棒全部完整跑完、零漏投、零不完整、一次都沒撞額度——本專案六個掃描 arc 以來第一次(決策者裁「一次只派一棒」的直接成果)。19 條發現去重歸成 6 張修正卡 CM-1629~1634(1 HIGH/4 MEDIUM/1 LOW),另 3 條併入 CM-1607,全部歸檔待 PM 安排。唯一的 HIGH 是 CM-1629:資料庫管理員密碼(=Redis 密碼,同一組)出現在 249 個版控文件裡,其中一份把主機/埠號/帳號/DB 名/密碼湊在相鄰兩行成為可直接使用的 POC 連線指令,而該帳號 BYPASSRLS;249 檔來源已查明——九成是 PGPASSWORD= 開頭的 Bash 指令被寫進對話紀錄(112 檔)與需求文件,全是文件無產品程式碼,同一機制已第三次(.env.test/JWT/本次),故該卡含治本項(改用 ~/.pgpass、歸檔前遮罩)。其餘:CM-1630 意見回饋六條端點只有匯出掛守門且改刪不驗歸屬(本專案第三次同款病)/CM-1631 Google Drive OAuth 密鑰與 Fernet 金鑰外洩(這兩把不是每套安裝各自產生的,要 Google 主控台重設)/CM-1632 連 GitHub 關閉 TLS 憑證驗證兩處(同款病第四處)/CM-1634 內部套件庫走明文 HTTP 且為 primary(橫跨 26 個 repo,供應鏈風險,I5 全新發現)/CM-1633 附件刪除守門只用一半(LOW,面板 0/3 否決但首腦不同意)。三條方法論:① 40 檔面板撐得住,前提是分開跑——FR-077 R1 的 42 檔全滅 vs I5 的 40 檔 15 票全投,差別在額度競爭不在檔數,尺改寫為「40 檔可行,一次只跑一棒」;② 工具會被程式碼註解說服(套件檔頭自稱「GitLab/GitHub 整合沒在用、佔 58%」,開卡前已證偽);③ 面板的「當前不可達」結論可信,但不會告訴你程式碼是不是寫錯的(I3 那條被否決的候選,面板漏看同一函式兩行用了不同變數)。工具在小範圍棒次會空轉:I3/I4/I6 三棒範圍內淨新增皆為 0,真正的產出全是首腦補查——含 I6 查出套件六張表完全無 RLS、連 tenant_id 欄位都沒有(比 FR-079 的 bulletin_org_units 更徹底)。總結報告見 SUMMARY.md。本 arc 原編為 FR-080,2026-09-09 因與「jedi- 套件整併與服務化路線」同日撞號,依登記表「最大整數號 +1」規則改為 FR-081(決策者裁;整併 arc 先開且已有 design/STATE/LOG,保留 FR-080)。 掃「意見回饋→問題單」這條鏈:使用者送意見,系統把它變成問題單,並可拿公司的存取權杖去 GitLab/GitHub 開一張真的 issue、還把使用者上傳的附件一起送過去*——要回答的是這條路上權杖會不會外洩、檔案會不會被放到不該放的地方、有沒有人能看到不該看的東西。🔴 三個發現改變了原本的評估:①套件檔頭自稱「GitLab/GitHub 整合沒在用、約佔套件 58%」是錯的——首腦從宿主端證偽,app/feedback/service/feedback_service.py 的 156/171/210/222/246/252 六處實際呼叫那些路徑(IssueProviderCode 統計 LOCAL 9/GITLAB 4/GITHUB 3),這正是工具已知盲點二(會被程式碼註解說服)的教科書形狀,照檔頭跳過就會漏掉最危險的一半,六張子卡每張都帶了這個警告;②首腦讀碼時已看到一個現成的洞——jedi_issue/infra/github.py:22 與 infra/issue/adapter/github/github_issue_adapter.py:43 兩處都是 Github(..., verify=False),帶著存取權杖走不驗憑證的 TLS,而這個模組的 PAT 外洩過一次(CM-1573 已 Done),首腦初判 HIGH(本專案同款病第四處,前三處為 CM-1560 LDAP/CM-1565 Redis/CM-1606 SMTP);③宿主那一半藏在 feedback/ 底下、用檔名 grep issue 會漏掉,這是 FR-079 教訓的直接應用。六棒按攻擊面切不按目錄大小平均切,順序依風險密度:I1 第三方整合與憑證 25 檔(jedi)→ I2 宿主接線 31 檔(BE repo)→ I3 附件上傳下載 14 檔 → I4 對外面與插件契約 20 檔(唯一一條 route /issue/get_members 吐成員名冊卻只有 @jwt_required(),檔頭自陳「缺接線要拒絕掛載不是跳過,跳過的後果是成員清單變公開端點」需驗證)→ I5 app 與 domain 層 40 檔(刻意略超 30 檔尺的邊界測試,因 app/domain 拆開會把用例編排與業務規則切在接縫上,而權限漏洞正活在那裡;面板若沒跑完不重跑整棒,回報首腦決定是否拆半,這輪數字會決定往後 30~40 檔區間的切棒尺)→ I6 持久層 28 檔。合計 158 檔(套件 127+宿主 31),約 7 小時純掃描。三組要放在一起看的關係:I1+I2 是同一條鏈的兩半(套件端怎麼打第三方 vs 宿主端輸入怎麼進來、權杖從哪讀、誰能觸發)/I4 的 fail-closed 宣稱 ↔︎ I2 的守門接線(兩棒都要驗,不要互相假設對方驗過)/I3 的就地 new repo ↔︎ I6 的 session 紀律。🔴 決策者裁:一次只派一棒,避免長跑中途撞額度導致結果不完整(FR-079 B2 跑了 14 小時、撞兩次額度、還踩到併檔陷阱);合理停損點在 I3 之後(I1+I2+I3 共 70 檔已涵蓋絕大部分風險面),但沒跑完六棒不能宣稱「jedi-issue 掃過了」。見 README |
relates to FR-075/076/077/078/079(掃描方法與教訓)/CM-1573(同模組 PAT 外洩前科) |
| FR-082 | 2026-09-10 | AI 聊天機器人(jedi-ai-bot)資安檢查 — ✅ 一棒掃完並經首腦驗收。stamp verified 且無拒收原因,七個 arc 以來最乾淨的一次(9 票全投、零漏投、零中斷、65 分鐘)。找到 1 條 MEDIUM(CM-1638):聊天端點沒有任何長度與次數上限——工具把「服務被拖垮」放在「燒錢」前面並追出完整的鏈:4 個同步工作程序 × Anthropic SDK 預設 10 分鐘逾時 × gunicorn 120 秒才砍,4~8 個並發請求就佔滿全部工作程序,整個產品所有功能停止回應;單則訊息天花板是主專案的 50MB(CM-1587),擋得到但等於沒擋。檢查員另主動去主專案與 nginx 設定查頻率限制(沒有)。修法三項:長度上限做成 AiBotConfig 可調欄位/AiBotService 加 request_timeout(讓上游卡住時自己放棄,不要等 gunicorn 砍)/頻率限制做成 adapter 插槽讓宿主用既有 Redis 實作。為什麼選這支掃(與跨 arc 總表建議的前五名不同):排名表按「檔數 × 授權鏈風險密度」排,判準裡沒有「資料外流」與「金錢成本」兩個維度,而這支是 25 支裡唯一同時具備兩者的(唯一把使用者輸入原文送出公司網路、唯一每次呼叫直接產生金錢成本);且 13 檔是最小的一棒,適合先把新的白話報告規則跑順。為什麼一棒不兩棒:宿主接線僅 3 檔 89 行(api/ai/ + infra/ai/),不值得單獨跑一棒,首腦全文讀完寫進卡片背景——這與 jedi-bulletin(宿主 33 檔)、jedi-issue(宿主 31 檔)不同。🔴 卡片點名的兩個重點工具一項都沒答,由首腦補查、兩項都是好消息:① 對話記錄跨不到別人那裡(chat_history:{使用者編號}:{對話編號},第一段由伺服器填且是數字,前綴偽造不了——首腦原本的擔心是錯的,但這道保護依賴「編號由伺服器填且排最前面」,已寫進修正卡建議加註解);② 缺認證設定時會炸是安全的(實測建構會成功但呼叫時 TypeError,不如 jedi-issue 的明確訊息友善但沒有洞,不開卡)。這是連續第二個 arc 出現「工具不照卡片重點清單走」(FR-081 的 I3/I4/I6 亦然)——卡片點名要查的項目,首腦要預期自己補查。記錄給下一棒:驗證指令的口徑要跟工具一致(卡片寫 13 檔、工具報 14 檔,差在工具算全部受版控檔而卡片指令只算 .py)。見 README、報告 |
relates to FR-075/076/077/078/079/081(掃描方法與教訓)/FR-079 F13(AI 儀表板旁路,同屬 LLM 資料外流面) |
| FR-083 | 2026-09-10 | AI 儀表板(jedi-ai-dashboard)資安檢查 — 🔄 兩棒掃完一棒。D2(宿主接線 18 檔)已驗收:stamp verified、33 票全投零漏投、面板主動降級 2 條、11 條發現(2 HIGH/9 MEDIUM)。範圍內 3 條全與「AI 儀表板繞過權限檢查」有關——F3 任何登入者可列出全公司帳號/角色/租戶/部門(同一個 UserService.get_users,正常網頁路徑要 @capability_required("user.read"),這條路完全不檢查;產品定義的四個權限點全繞過,攻擊只需一個普通帳號+一句 prompt)/F9 回應夾帶每個帳號的密碼鹽值(UserDTO 帶 salt 欄位,正常列表刻意排除、儀表板這條路沒過濾,前端只顯示幾欄是顯示行為、後端已送出)/F10 專案清單 is_admin=True 後門(🔴 首腦開檔查出這是刻意設計不是寫錯——docstring 自陳「對齊 v1 dashboard 看本 tenant 全部專案,tenant 隔離由 RLS 負責」,真正的問題是那個決定在「使用者打字、AI 自己決定查什麼」的新情境下沒人重新檢視過;修法要先做產品決策,直接拿掉可能弄壞既有行為)。範圍外 8 條密鑰專項順手撈到,其中 2 條是新的:F1 GitLab 權杖在版控文件、F2 Nexus 管理員帳密+MinIO 金鑰在交接文件——與 FR-081 的 CM-1634(同一套件倉庫走明文 HTTP)是同一目標的兩面,合起來供應鏈風險高於單看任一條。⚠️ 卡片點名的核心交付「27 支 API 權限形狀表」工具只做了 5 支(auth 4+project 1),其餘 22 支沒碰(participant 7 支風險僅次於 auth)——連續第三個 arc 出現「卡片點名的重點工具沒答」(FR-081 三棒、FR-082 A1),已寫進總表 §3.4,建議 D1 驗收時由人補完。🔴 決策者裁「修正卡先不開,之後從總表決定要修哪些」,三條已登記進跨 arc 總表 §3.1(含具體修法與行號)。D1(套件本體 34 檔)尚未跑——它要回答「使用者能不能用打字誘導 AI 去選那些沒防護的 API」,兩棒發現要放在一起看。見 README、D2 報告 |
relates to FR-079 F13(本 arc 的起點)/FR-082(同屬 AI 功能面,共用同一把 AI 金鑰)/FR-081(CM-1634 套件倉庫明文連線,與 F2 同一目標) |
| FR-084 | 2026-09-10 | 防竄改機制(jedi-integrity)資安檢查 — ✅ 一棒掃完並經首腦驗收(2026-09-10)。stamp verified、6 票全投,但工具正式發現 0 條、六條全靠 runner 人工開檔查出(連續第四個 arc 工具不照卡片重點走,這支十項重點工具只碰一項)。結論:擋得住隨手改檔案,擋不住有主機權限又知道機制的人。 兩條 HIGH:驗簽章的 cryptography 落在開機不核對的 thirdparty 層(BE build 腳本把 pdfminer 的相依一併排除原樣複製,build_release.sh:365),換掉它整套保護永久失效、抽查也一起失效——跨 repo 的洞,單一 repo 掃描讀不到;文件宣稱兩道鎖實際一道(TamperEventRepo.exists 兩 repo 零呼叫者),刪一個檔就能重開被鎖機器(面板 1:2 否決、首腦翻案維持 HIGH,理由是對「湮滅紀錄」的人成立)。首腦降級一條:GUIDANT_RESOURCE_ROOT 換執法對象要先過 cryptography 那關,是放大器不是獨立路徑,HIGH→MEDIUM。另 nonce 帳毀損取寬鬆側(M)、鎖定殼對外公開指紋(L)、回報夾帶 log 尾段(L)。六條全未實測(紀律不動 /opt/guidant/pki),依決策者裁定不開卡、登記總表 §3.1 第 13~18 項,cryptography 那條建議開卡前先在本機造假產物實測。母卡 CM-1644、掃描卡 CM-1645。落地版產品裝在客戶機器上、任何人都能直接改檔案,這支套件負責開機逐檔核對原廠簽章、被改就拒啟鎖定、只有原廠簽的一次性解鎖檔能解。風險形狀與前七個 arc 不同:被攻破的後果是「保護失效」不是「資料外洩」,所以每條發現要問的不是「需不需要主機權限」而是「有了主機權限之後繞過保護還要不要額外成本」。首腦讀完 21 檔+宿主接線後看到四個可能零成本的點(寫死在卡):①整套保護只有一個開關 is_packaged();②啟動只看檔案系統的鎖定標記、從不查 DB(README 宣稱的「雙落點任一存在即拒啟」在程式碼裡不成立,TamperEventRepo.exists 零呼叫者);③鎖定標記/解鎖檔/已用 nonce 帳同一個可寫目錄且 nonce 帳毀損取寬鬆側;④驗簽章的 cryptography 可能落在啟動不核對的 thirdparty 層。一棒不兩棒:宿主接線只有 common/integrity/adapters.py 357 行+5 個呼叫點,首腦全文讀完寫進卡片背景(比照 FR-082)。不在 FR-080 整併名單,掃完永久有效。見 README |
relates to FR-064(原始實作)/FR-076(CM-1572 曾順手撞到它一條 HIGH)/FR-075~083(掃描方法與教訓) |
| FR-085 | 2026-09-10 | 共用地基套件(jedi-common)資安檢查 — ✅ 三棒 91 檔全部掃完並驗收(2026-09-11 arc 收口)。jedi-common 這支「25 支套件共用的地基」至此首次有完整、算數的掃描(先前只有一次未經面板的半途掃描)。三棒合計 22 條(2H/9M/6L,另 5 條查證為無問題或死碼),依決策者裁定修正卡不開、全部登記跨 arc 總表 §3。C3(輸出面與打包 30 檔):18 票全投、工具 4 條+人工 6 條——密碼遮罩遇到含雙引號的密碼只遮一半、剩下半截原文寫進 api_logs 留 90 天(common_utils.py:159-165 用正規表示式做遮罩,值裡有 " 就斷掉,受害的正是 LDAP/SSH 那類強密碼;修法要改用 JSON 解析遞迴遮罩)/分頁「一頁幾筆」無上限(schema/common.py:13,CM-1587 的 body 上限擋不到這種小輸入大輸出)/安裝套件走明文連線這條與既有 CM-1634 是同一件事(從 jedi-common 這側再次獨立撞到,佐證它橫跨全部 repo)。開卡時的六個疑點三成立三證偽(can_manage_orgs 與 log 操作者可偽造都是死碼、信封失敗那條進不去)——懷疑清單有一半被推翻是健康的。C2(log 全鏈 32 檔):stamp verified、12 票全投,但工具正式發現 0 條、七條全為人工查證(連續第五個 arc 工具產出遠低於人工)。唯一 HIGH:登入密碼與 JWT 憑證原文寫進 log/app.log 與 system_logs(common/middleware/app_mw.py:45-46 印完整標頭與 request body 零遮罩,而同檔 :51 寫 api_logs 前有呼叫 mark_password()——同一支檔案一條有遮一條沒遮)。連帶查出出貨設定漏 RUN_ENV(guidant.env 24 行無此變數 → config_logger.py:44 退回 dev),客戶正式機實際跑開發用 log 設定,把前面幾條的影響從開發機擴大到客戶機——一行可修、投報率最高。首腦 DEV 實查複核 system_logs 無客戶隔離(RLS 關閉、0 條規則、12 欄無 tenant 欄位、668,813 筆,api_logs 同樣無隔離)。卡片認定「最重要」的那條(log 操作者可偽造)查證為死碼不成立。C1 結果:stamp verified、24 票全投(8 候選×3 檢查員),工具 3 條(2 HIGH 1 MEDIUM)+首腦人工 2 條。兩條 HIGH 是同一個洞、就是既有的 CM-1559(無登入身分時 RLS 整個關掉),本棒的新資訊是它比原本記錄的更好觸及——登入端點每次都經過,且有一個完全沒守門的 Google Drive webhook(同目錄其他每條 route 都掛 jwt_required)。新發現兩條:SQL 錯誤原文直接回前端(含表名欄位名與撞到的值,三票一致通過)/主產品 Redis 連線不驗憑證——CM-1565 在 jedi-iam 修好但主產品這份漏網的複製品(修法與測試都現成可抄)。卡片點名的兩個重點被工具一致否決、首腦認同:f-string 拼 SQL 目前無可控值到得了(但寫法仍脆弱、建議改參數化)、can_manage_orgs 無條件為真是死碼(105 條 policy 零命中,建議刪)。⚠️ runner 未交付報告與 Notion 回寫,由首腦補做。jedi-common 是 25 支套件與主產品的共用底層:每次 DB 存取都經它的 session_scope 注入 RLS 變數、每個錯誤回前端的格式由它決定、每行 log 怎麼寫也是它——它出問題等於 25 支全中,而至今沒有一次算數的掃描(只有第一輪 medium 半途未經面板)。按業務功能垂直切三棒:C1 授權鏈核心(session+identity+handler,29 檔)/C2 log 全鏈(logger,32 檔)/C3 輸出面與打包(interfaces+utils+enums+constants+.env+publish.sh,30 檔);handler.py↔︎response_util.py 是接縫,兩卡互相允許越界讀。首腦核過的現成疑點:RLS session 變數用 f-string 拼進 SQL 無 bind param(db.py:95/108/113,獨立於 CM-1559 的注入面)/每個登入者無條件 can_manage_orgs='t'(db.py:98)/log 操作者取自 request header X-UserId 且 BE、FE 無人設它(middleware.py:13,稽核身分可偽造)/SQL 例外原文回前端(sql_exception.py:37-38)/信封失敗把例外訊息當 data 回前端(response_util.py:26)/page_size 無上限/gen_comment.py 帶 OpenAI key 又用未定義變數覆寫原始碼、零 importer。偵察由唯讀 subagent 做、行號首腦逐一開檔核過。見 README |
relates to CM-1559(RLS fail-open,C1 基準線)/CM-1598(.env 受版控,C3 基準線)/FR-083 D1 F2(to_serializable 是否系統性問題,C3 要答)/FR-075~084(掃描方法與教訓) |
| FR-086 | 2026-09-11 | 檔案上傳下載(jedi-file-upload)資安檢查 — ✅ 三棒 71 檔全部掃完並驗收(2026-09-12 arc 收口),合計 14 條發現(6 HIGH/4 MEDIUM/4 LOW,另 7 條查證為無問題)。🔴 「四層全空」已由三棒各自坐實:網址入口只驗登入(B1)/業務邏輯零檢查(B2)/資料查詢無範圍條件/資料表無租戶欄位且隔離關閉——B1b 用 DEV 實查坐實(relrowsecurity=false、規則 0 條、tenant 欄位 0 個、2,690 筆,首腦複核四個數字全對)。這條的證據等級是本 arc 最高的:前兩棒只能引建表腳本自陳,這一棒是資料庫本人回答的。B1b 另查出三後端不一致:主機硬碟後端刪檔漏清轉檔快取(物件儲存那邊會清),等於「刪了但沒真的刪掉」,對稽核產品是實質缺陷;報告 §5 給了完整三後端對照表,不一致的四項全是主機硬碟那支缺了物件儲存那支有的東西,建議把共通邏輯往上提而非再複製一份。證偽三條:路徑穿越(兩側各證偽一次,但都是執行順序意外擋住的、不是刻意防的,重構會長回來)、系統指令注入(兩處都用陣列形式、無 shell=True、路徑不含使用者輸入)、工廠退路(拋錯 fail-closed,做得對)。⚠️ B1b 工具達標 0 條(2 條候選全被 1:2 否決),5 條全為人工查證——卡片八個重點工具只碰到一個半,包含證據等級最高的那一條;且無逐檔閱讀帳本,不可宣稱這 26 檔乾淨。🔴 B2 證實這條路四層全空:網址入口只驗登入(B1)/業務邏輯零檢查(managed_file_upload_service.py:352-362 三方法各一行,挑後端的 :173-178 docstring 自陳只看檔案自己記的 scope、不看人)/資料查詢無範圍條件/upload_files 表無 tenant 欄位且 RLS 關閉(首腦 DEV 實查 relrowsecurity=false、0 條規則)——沒有任何一層會問「這個檔是不是你的」。B1 與 B2 必須同一張卡一起修,只修一邊等於沒修。🔴 人工另追出一條同級的:任何登入者打一支查設定的 GET 就拿到本租戶物件儲存的位址/帳號/密碼明文(遮罩清單 :36 未收錄 STORAGE_CONFIG、敏感欄位名 :39 未收錄 access_key/secret_key、兩支 GET :205/:370 只掛 jwt_required 而同檔更新刪除建立三處都有能力檢查、連查快照那支唯讀端點都有),拿到後可完全繞過系統直連倉庫,應用層補再多都管不到;評 HIGH 不評 CRITICAL 是因 system_configs 有 RLS(實查 4 條規則),範圍限本租戶。⚠️ 工具注意力被稀釋:12 條候選 9 條是範圍外憑證重複,36 票有 27 票投在範圍外,真正投在這 10 檔的只有 3 票,範圍內兩條有份量的全是人工追出來的。🔴 B1 找到 4 條(3 HIGH/1 MEDIUM),是目前所有未開卡發現裡最直接可利用的一批:只要一個能登入的帳號+知道某個檔案編號,就能下載/預覽/永久刪除別家客戶的檔案,還能換發一張免登入的下載通行證傳給公司外面的人(upload_file_route.py 的 :172 下載/:152-156 發證/:114-118 刪除三個端點全部只掛 @auth_required,無歸屬檢查;資料層 get_by_uid 只 filter_by(uid=...),那張表又無多租戶欄位、資料庫層零兜底)。另一條 HIGH 是儲存型 XSS:預覽端點依使用者給的副檔名猜 Content-Type 且 as_attachment=False,上傳一個網頁檔、別人一點預覽就在我們自己的網域執行,而副檔名完全沒有白名單。四條同病、共用一道修法(三個端點加歸屬檢查),修一次解四條。 ✅ 卡片列為「本棒最重要」的路徑穿越經查不成立——set_save_dir 寫的是設定物件、但 adapter 建構時已把目錄抄走,攻擊字串追不上(首腦獨立核對執行順序屬實);但那是靠執行順序意外擋住的、不是刻意防的,重構就會長回來。產品所有上傳/下載/預覽都經過這支:檔案存到哪(主機硬碟/物件儲存/客戶設備)、存成什麼檔名、下載時怎麼判斷「這個檔是不是你的」。存檔案的那張表沒有多租戶欄位(建表腳本檔頭自陳),資料庫層零兜底、應用層的歸屬檢查是唯一防線。首腦盤點到五個現成疑點,行號已開檔核對,其中三條若都成立就是一條完整的跨租戶取檔路徑:① 上傳時用使用者可控的字串拼存檔路徑(upload_file_route.py:101,os.path.join(payload['upload_type'], payload['uid']) 未見 ../ 過濾)/② 任何登入者可替任意檔案編號換下載憑證(:150-156 只掛 @auth_required,無歸屬檢查)/③ 查檔案的資料層完全沒有範圍條件(upload_file_repo_impl.py:41-45 只 filter_by(uid=...))/④ 檔名處理薄(無白名單、無正規化、無單檔大小上限)/⑤ 物件儲存憑證存 JSONB 且加密預設為關。三棒是一條路徑的三段:B1 查「請求進來時路徑是不是使用者可控」→ B2 查「挑後端時有沒有驗歸屬」→ B1b 查「落地時有沒有兜底」,驗收時互相對照。砍掉原規劃的第四棒(remote_agent 檔案通道)——查證與 FR-077 CM-1594 範圍完全重疊,要掃那條請派該卡。檔數已核對:排名表寫 61 檔/2,510 行,實際 68 檔/2,877 行,低估約 11%。見 README |
relates to CM-1594(FR-077 R3,重疊已去重)/CM-1633(FR-081 I3 另一支套件的附件功能)/CM-1559(FR-085 C1 無身分時隔離關掉) |
| FR-087 | 2026-09-11 | 租戶隔離破洞盤點 — ✅ 已盤完並經首腦驗收(卡 CM-1663,一棒只盤不修、不用掃描工具,與 FR-086 B1b 平行跑、不搶額度)。逐表五問全答、修法分七組:甲純開開關(compliance.projects/tenant_drive_integrations)/乙補 4 條規則再開(8 張)/丙補 SELECT(workflow_executions)/丁 4 支畫面加 security_invoker(必須與丙同輪驗證,待辦列表跨 12 張表含丙那張)/戊要先回填資料(workflow_templates 191 筆凍結副本無客戶歸屬,首腦實查 17,544 筆中 191 筆為空、其中 132 筆仍連著使用中的流程,直接開會讓使用者看不到自己稽核流程的凍結範本)/庚等決策者裁(問卷平台旗標,報告 §7 給三選項)/辛建議重新分類(log_forwarding_settings 本質平台層、已有能力點守門,不算隔離缺口)。🔴 本棒最有價值的是兩項查證:① 兩支背景排程(每天 03:10 掃 job_executions 全表找孤兒、01:00 清框架解析)靠「無身分時暫時給最高權限」運作(程式註解自陳,首腦核對屬實)——開隔離不會斷它們,但 CM-1559 那條 fail-open 收緊那天會安靜停止運作、不報錯、孤兒堆積沒人發現,兩件事必須同一輪規劃;② 更正交接檔一處推測——平台管理員判定 viewer_is_platform_admin() 呼叫的正是 RLS 判「是不是最上層租戶」的同一段邏輯(_session_paths_have_root),是合法的上層看下層、不是靠隔離沒開才漏看得到,開隔離不影響管理後台。另更正交接檔「三支 view」實為四支。來源是 FR-080 併入當日的交接:決策者實測發現切到被指派的子租戶後仍看得到別家客戶的待辦與專案,裁定隔離修正歸資安線、與 FR-086「只驗身分不驗歸屬」那批一起看。已實測、非理論風險(首腦在 DEV 用受隔離帳號重跑,與交接檔一致):拿指向不存在租戶的鑰匙查,待辦應 0 筆實際 39 筆、專案應 0 筆實際 213 筆、任務執行 11,065 筆、工作流執行 11,016 筆。缺口:13 張有租戶欄位但隔離沒生效的表(3 張政策寫好只差開開關含 compliance.projects/1 張缺 SELECT/9 張連政策都沒有)+4 支 view 繞過隔離(PG16 預設用擁有者身分查底層,而擁有者是超級權限帳號;⚠️ 交接檔摘要寫三支,實際四支)+任務詳細 API 收了專案編號卻從頭到尾沒用它(job_route.py:75-92,首腦開檔核對屬實,與 FR-086 B1 同型可併)。本棒最重要的不是列清單,是回答「開了隔離會不會弄斷現在的功能」——統計儀表板(FR-083 已查出 27 支查詢不經權限檢查)、背景任務(交接檔說走無身分路徑不會斷,但那條正是 CM-1559 的 fail-open,兩件事必須一起規劃)、平台管理功能三類要逐一查。為什麼不用掃描工具:答案在資料庫狀態與 SQL 不在程式碼漏洞模式,人工快又準,且這樣才能與 B1b 平行不搶額度。FR-080 其餘收口七項歸 FR-080 首腦,不在本 arc。 見 README |
relates to FR-080(來源交接)/FR-086(同型,四層全空)/CM-1559(無身分時隔離關掉)/FR-083(AI 儀表板 27 支查詢) |
| FR-088 | 2026-09-12 | 流程引擎(jedi-flow-engine)資安檢查 — 🟡 已開卡待派(母卡 CM-1669、子卡 CM-1670~1675,一次建完連號)。套件 72 檔+宿主 92 檔(總表原估宿主 60-80,實數更多),按業務功能垂直切六棒共 150 檔:H2 任務完成/回退/留言/證明(23,BE)→ H1 稽核階段推進與回退(21,BE)→ P1 流程圖範本與 BPMN 解析(30,jedi)→ H3 流程範本管理(13,BE)→ H4 流程執行宿主服務與接線(21,BE)→ P2 流程執行核心(42,jedi)。排序判準是「可利用門檻」不是嚴重度。首腦讀碼核過的三個最值得先驗的疑點:① 推進/回退階段時專案 uid 與輪次 uid 各查各的、從不核對(stage_advance_service.py:529-587,A 專案 manager 可能推進 B 專案的稽核);② 流程留言 GET/PUT 與任務證明兩支 GET 只驗登入不驗歸屬(flow_engine_route.py:44-121、job_evidence_service.py:43-71),而 element_variables/job_evidences 隔離關、零規則、無租戶欄——與 FR-086 同病;③ force 旗標雙版本(權限檢查看外層、handler 讀 ctx.force,stage_advance_service.py:209/303 vs oscal_stage_handlers.py:41)。DEV 唯讀實查:流程相關 10 張表只有 flow_templates 一張隔離是開的,FR-087 只盤了 3 張,另 7 張為本 arc 新增實況。一次只派一棒,合理停損點在第 3 棒後。見 README |
relates to CM-1559/FR-087(三張表與 191 筆無主凍結副本)/FR-083 D2(儀表板申報 API)/FR-079 F13(**kwargs 掉過濾)/FR-086(四層全空清單) |
| FR-089 | 2026-09-12 | 套件結構統一(jedi-asset 定形 → 主專案側收斂 → 21 支套件套用)— 🟢 全案 Done、套件 1.0.1 已出版,主體待進版。三段全收、arc review 與修正卡全修、21 支推 Nexus(20 支 1.0.1、oscal-v2 2.3.1)、主專案 pin 正式版驗過。餘 DI 瘦身三卡(併 1.1.0)與 version-bump 1.20.0(等令);出貨升級鏈接續 FR-093、租戶隔離 FR-094。 | |
| FR-090 | 2026-09-12 | 主專案側殘留收斂(套件上移後的空殼、port 實作、轉發殼與 wrapper)— 🟢 七棒 Done(2026-09-13):空殼清理/port 歸位/iam 收斂/補暱稱走 D8/接線收 core/plugins//第 7 棒最後三支(ai-bot/ai-dashboard/remote-agent)收進,主專案側 21 支同形。待裁:第 6 棒 DI 瘦身 CM-1696、主專案 36 筆能力點申報處待開卡。見 README |
relates to FR-089(母案)/FR-069 D8 |
| FR-091 | 2026-09-12 | 21 支 jedi-* 套件套用標準形狀 — 🟢 28 卡全 Done、21 支已推 Nexus 1.0.0(2026-09-13)。21 支照 jedi-asset 形狀(三批+iam/detection/task-platform 大卡+oscal-v2/common 輕量版)+能力點宣告(21 支 80 筆 CAPABILITIES+主專案五條守衛對 seed)+版面殘留三條線+PM 白話頁 CM-1736。arc review 與修正卡歸 FR-089 收口。見 README |
relates to FR-089(母案)/FR-090(前置)/FR-069 D8 |
| FR-092 | 2026-09-12 | 主專案廢碼清理(套件搬移後沒人引用的 73 檔、沒人打的 12 支端點、前端 15 檔備份頁)— 🔵 進行中(母卡 CM-1703;盤點四棒 CM-1708~1711 Done;修正卡 CM-1704~1707+CM-1717~1724 共 12 張待派)。用「從 main.py 入口可達性」找出零活路徑的檔案、227 支端點對 FE/agent/e2e 三方核對;四棒純刪不改行為。刻意不碰 FR-090/091 要動的 shim 與 detection/iam;四張盤點卡與修正第 1/2/4 棒現在可派,僅第 3 棒等 CM-1700/1701。cloner 查證為 FR-038 掏空的殭屍非漏接。見 README | relates to FR-069/FR-090/FR-091/FR-038/FR-048 |
| FR-093 | 2026-09-13 | 出貨升級鏈補齊(套件自帶的表、權限、選單,客戶升級時自動到位)— 🟡 十棒完成八棒(2026-09-14,母卡 CM-1752)。.1 出貨線接套件 migration 四棒全完、.2 能力點自動到位三棒全完、.3 選單守衛與 24 支 SQL 冪等核對兩棒完成(SQL 全數通過未改一支),只剩 .3c 套件補選單資料+發 jedi 1.1.0(等令)。🔴 已知缺口:新裝路徑資產狀態 enum 仍大寫——要對 188 基線庫套一次 asset 002 + 重產 02-schema.sql 才會好,屬動出貨基線,決策者 2026-09-14 裁示先不做、列出貨前待辦。定下長期規則 D3:套件疆界的表往後只在套件改。進度與缺口見 README |
relates to FR-089/FR-091(套件形狀)/FR-065(migrate 模式)/FR-062(licensed_modules) |
| FR-094 | 2026-09-13 | 租戶隔離修正(RLS 第三波:13 張表+4 支 view 真的把「每個客戶只看自己資料」關上)— 🟢 已開卡待派,前置 CM-1559 In progress(母卡 CM-1766;子卡 CM-1767~1773 七張+既有 CM-1559 共 8 棒,三子需求:.1 前置與套件/.2 開隔離/.3 問卷裸表)。內容來源 FR-087 盤點;D1 公版沿用 policy 旗標 OR 分支不動 helper、D2 問卷不加公版旗標改修 12 張裸表、D3 projects 補分支後重開;順序硬相依:.1a 排程系統身分 → CM-1559 收緊 → .2c 開 job_executions/framework_parse_jobs。吸收 CM-1445/CM-1453 結案。只套 DEV+基線庫,STG/POC 等放行。見 README | relates to FR-087(盤點)/FR-075(CM-1559)/FR-069.16/FR-086(§4 應用層洞歸該案)/FR-093(套件 migration 攤平) |
| FR-095 | 2026-09-14 | 任務平台(jedi-task-platform:專案成員、任務指派、任務執行)資安檢查 — ✅ 已掃完(2026-09-15)。三棒 P1/H1/P2 共 109 檔,首腦逐棒驗收;發現登記總表 §3.1 第 60~71+§3.2 第 17~23,已全數修好,隨 1.21.0 出貨。母卡 CM-1779。 | relates to FR-086(四層全空清單)/FR-088(H4 9 檔可讀不報、第 51/59 條)/FR-083(儀表板申報)/FR-087/FR-094(projects/job_executions 由 CM-1768/1770 接走)/FR-075(CM-1559) |
| FR-096 | 2026-09-15 | 系統設定與選單字典(jedi-system-core:寄信/LDAP/物件儲存的伺服器設定)資安檢查 — 🟡 已開卡待派(母卡 CM-1803、子卡 CM-1804~1806,一次建完連號)。這支的風險形狀與前面幾支不同:前面掃「誰能看誰的資料」,這支存的是系統自己的鑰匙(寄信/LDAP/物件儲存帳密)與全站生效的總開關。套件 57 檔+宿主 25 檔,切三棒 82 檔:P1 設定表全鏈+插件契約與四道守門殼(24,jedi)→ H1 主專案接線:守門版服務+繞隔離讀寫器+四支 DI 組裝(25,BE)→ P2 選單字典全鏈(33,jedi,含 13 空檔)。首腦開卡時已開檔核出三件事:① 四處繞過守門版服務用未包裝原版(auth_containers.py:180/notification_containers.py:20/user_change_password_containers.py:46+login_containers.py 直接接底層),這四條路徑是登入/寄信/改密碼,全會碰到 SMTP 密碼;② 讀設定把整列(含密碼原文)寫進日誌(system_config_service.py:20),是總表「密碼寫進日誌」FR-085 C2 的源頭表;③ 遮罩名單漏掉 STORAGE_CONFIG 且機密欄位名沒有 access_key/secret_key(plugin/contract.py:61/:65),與 FR-086 B2-A 同根因待確認。DEV 唯讀實查:設定表有隔離(4 條規則)、23 筆分佈 6 客戶、6 筆密碼欄位有值;選單表無隔離但 74 筆全是碼表無個資,已查證為正確設計、掃到不要重報。一次只派一棒,停損點在第 2 棒後。見 README |
relates to FR-085(C2 密碼進 log)/FR-086(B2-A 遮罩名單漏儲存組)/FR-093(套件自帶 migration)/FR-094(RLS 第三波)/FR-095(前一支掃描 arc)/FR-075(方法論與 STATE) |
| FR-097 | 2026-09-15 | 系統日誌轉送與 API 操作記錄(jedi-log)資安檢查 — 🟡 已開卡待派(母卡 CM-1810、子卡 CM-1811~1812,一次建完連號)。這支從來沒掃過,風險形狀特殊:日誌本身就是最敏感的資料——依總表第 22 項,登入密碼與憑證會原文寫進日誌,所以「日誌要送去哪裡」這個設定被改掉,等於把含密碼的整包資料持續、悄無聲息導向攻擊者的機器。套件 90 檔,按「改設定會怎樣/誰讀得到」切兩棒 82 檔:L1 日誌轉送全鏈(39,jedi,含 2 支 SQL)→ L2 API 操作記錄全鏈(43,jedi,含 2 支 SQL)。首腦開卡時已開檔核出的最大疑點:🔴 改「日誌送去哪裡」的權限 log-forwarding.update 是客戶層級(DEV 實查 is_platform=false,依租戶開通邏輯每開一個新客戶就自動發給該家管理員),但設定表只有全域那一列(tenant_id 為 NULL,建表腳本檔頭明寫「第一版是系統層全域一份」)——與 FR-096 H1 查到的第 74 項完全同形(客戶管理員可改全公司登入規則,已證實成立)。已查證、掃到不要重報三件:① 三支轉送端點在套件裡沒掛裝飾器是刻意設計,守門由宿主注入(已追到 core/plugins/api_log.py:185-186 確實注入「要登入+要有權限」且讀寫分權),這是本 arc 最可能的誤報來源;② 轉送設定表刻意不掛 RLS(平台層設定、且掛載在無請求脈絡的背景執行緒,掛了會讓背景讀取恆空);③ 操作記錄表無隔離無客戶欄位已登記總表第 23 項、不另計。開卡時更正總表一處錯誤:§4 排名表原寫「日誌轉送的目標設定裡包含帳密」——逐欄核對後確認不成立(只有主機/埠號/協定/開關,無任何帳密欄位),該支排序理由已改寫。停損點在第 1 棒後。見 README |
relates to FR-085(C2 密碼進 log,本案風險前提)/FR-094(RLS)/FR-096(第 74 項同形)/FR-075(方法論與 STATE);jedi-asset 為下一支,宿主接線棒兩支合併 |
| FR-098 | 2026-09-16 | 設備與資訊系統資產(jedi-asset)資安檢查 — 🟡 已開卡待派(母卡 CM-1813、子卡 CM-1814~1815,一次建完連號)。決策者指定 log 掃完接這支。這支從來沒掃過。套件 60 檔(去重後),按「設備/資訊系統」切兩棒:A1 設備全鏈+套件共用骨架與三支 SQL(45,jedi)→ A2 資訊系統全鏈+共用骨架重疊帶入(42,jedi)。兩棒相加 87 是因為共用骨架 27 檔刻意兩棒都帶——守門殼/插件契約/錯誤碼/資料存取底層是兩半共用的,切在接縫上兩棒都看不到全貌,重複報由首腦驗收挑掉。兩份檔數皆於開卡當下實跑 git ls-files 驗過。🔵 與前幾支風險形狀不同:資料庫隔離做得好(DEV 實查:設備表開隔離+4 條規則+有租戶欄+3 筆;資訊系統表開隔離且 FORCE+4 條規則+91 筆),風險集中在程式層權限檢查,不可沿用 FR-086/FR-095「資料庫層全空」的預期。首腦開卡時已開檔核出的最大疑點:🔴 兩支 route 檔的讀取類端點全部只掛 @auth_required、寫入類每一個都有 @capability_required(設備 device_route.py 清單 :37/選單 :56/明細 :68/被引用 :106 vs 修改 :78/刪除 :90;資訊系統 information_system_route.py 選單 :42/清單 :59/明細 :102 vs 新增 :82/修改 :114/刪除 :135)——與 FR-096 第 72 項、FR-097 第 75 項完全同形,該兩條均已證實成立列高風險。已查證掃到不要重報:八個權限點皆客戶層級屬正確(資產清冊本該客戶自管);兩張表隔離設定刻意不同(設備只 ENABLE 不 FORCE,檔頭理由是其 insert policy 無 super admin 逃生門且要求 org 相符,FORCE 會擋掉 org 為空的使用者)——但檔頭同時自陳「owner 為 cm_app 時只開 ENABLE 等於沒開」,設備表正是只開 ENABLE,這是 A1 的核心問題。宿主接線 12 支兩棒都不含,將與 jedi-log 根層 6 支合併成獨立一棒(18 檔,BE repo),兩棒跑完再開卡。見 README |
relates to FR-094(RLS 第三波)/FR-096(第 72 項同形)/FR-097(前一支掃描 arc、宿主接線棒合併對象)/FR-075(方法論與 STATE) |
| FR-099 | 2026-09-16 | 意見回饋與標籤併入 jedi-issue — 🟡 已開卡待派(母卡 CM-1816、子卡 CM-1817~1819,一次建完連號)。決策者 2026-09-16 review 主專案剩餘 route 時點出的漏網(非欠債):主專案 api/feedback/(4 條 route)與 api/label/(1 條,全檔 23 行純轉發殼)實際上整條鏈都在呼叫 jedi-issue,但前幾輪模組化(FR-069/FR-080)是按目錄掃的——api/issue/ 搬走了,這兩個另外命名的目錄沒被認出是同一件事。首腦實查證據:app/feedback/service/issue_service.py 24 處呼叫套件 IssueService(全帶 provider=LOCAL);feedback_issues 只有四欄是純關聯表,標題內容靠 relationship 從套件 issues 表撈;DEV 庫 issues 23 筆/labels 35 筆/feedback_issues 14 筆;FE 三處打 /labels/menu 全在 views/feedback/ 底下(標籤是回饋的附屬品不是獨立功能)。🔴 同時抓到套件 README 兩條錯誤聲明——寫著「Issue 本體產品目前未使用」「GitHub/GitLab 產品目前沒在用」,兩條皆與事實不符,且該段緊接著寫「不要順手清死碼」,等於事後幫這個漏洞蓋章:後續每輪盤點的人讀了都會跳過這塊。故第 1 棒刻意切成純文件的止血棒並排第一。決策者已拍板:GitLab/GitHub 外部整合保留、整組搬進套件(連同 FE 設定頁視為正式功能,python-gitlab/PyGithub 兩支相依留著);對外 URL 一字不變。三棒:README 更正(2 檔)→ 主體搬遷(五目錄刪除,跨 BE+套件兩 repo)→ 外部整合設定歸位與殘留清查。首腦已核出待第 2 棒處理的四個雷:project_name = "CM" 寫死在 issue_service.py:41(產品知識不可進通用套件,須改 config 欄位);label_repo/label_domain_service 在兩個 DI container 各建一份(違反 FR-090 第 6 棒規則);feedback_issues owner 是 cmmgr 而套件六張表是 ammgr(歸屬要跟著改,且 jedi-issue 沒有 migrations/ 目錄須新建);FeedbackIssue model 兩個 hybrid_property 自己 join User 補暱稱(違反 D8,須改走 identity port,但 .expression 那半進不了 port 要另想)。已列明待決策者裁三項:feedback-view.read 命名要不要統一;三條 route 宣告了能力點卻只守登入要不要補;feedback_issues 可否併進套件 issues 表。見 README |
relates to FR-069/FR-080(模組化母源,本案是其漏網)/FR-090(主專案側收斂五規則,本案沿用)/FR-093(隨包 migration 落點待查) |
| FR-100 | 2026-09-16 | 主專案剩餘 route 逐支盤點結論 — 📋 純記錄不派工(卡 CM-1820)。決策者 2026-09-16 問「為什麼還有很多 route 在主專案」,逐支查完 20 個 api/ 目錄的結論。三支待處理:① user_auth_provider(285 行)與 FR-099 同型漏網——jedi-iam 已有全鏈(entity/repo/domain+app service/LDAP adapter/auth_provider port),主專案是殼,但 🔴 app/user_auth_provider/service/ldap_service.py 有兩條資安防護不可無腦搬(CM-1283 讀不到 ROOT 列會把 LDAP 密碼靜默清空而畫面顯示成功;CM-1564 主機位址變更時沿用舊密碼=把服務帳號密碼送去任意主機),須走 port;② translate(94 行)前端零入口——api.js 連常數都沒有、ui_routes 零命中,只剩孤兒 error code 字串,帶著 openai 相依與 OPENAI_API_KEY;③ report(130 行)前端零入口但砍前要查證——ui_routes 舊選單 report-view enable=0,開著的 report-manage 指向 /project-summary-report 是另一支;但它有 D14 path traversal 防護且讀 SCHEDULE_REPORT_DIR,可能給排程/外部系統用。順帶抓到:FE 意見回饋有兩組頁面,views/feedback/cruising/ 舊組選單已關(ui_routes id=14 enable=0)但路由仍掛著(router/index.js:76-102)且打同一組 API、下拉走 SYSTEM_MENU 而非 LABELS_MENU——已通知 FR-099 第 2 棒驗收不可只測一組。其餘不動:cloud_integration(6,101 行真業務,決策者明確裁不動)/oscal(套件刻意零 route,是資料層函式庫)/flow_engine(已知已排程的債非漏網,設計稿與 D-1~D-9 已拍板但 226 檔四步未開卡;決策者裁套件未發布故實際傷害為零,POC 前不動)/業務層各支。🔴 盤點方法入卡:判斷前端有沒有在用不能只 grep 原始碼(決策者要求),要查三層——api.js 常數/FE 路由/DB ui_routes(真相來源,欄位是 name/url/enable,DEV 現況 43 開啟 12 關閉);三層矛盾本身就是線索。建議順序(POC 後裁):user_auth_provider → cruising 退役+report/translate 查證 → 兩支退役;flow_engine 不排期。見 README |
relates to FR-099(同一次 review 的第一支漏網,執行中)/FR-092(廢碼清理同類)/FR-080(終局形狀定義)/FR-104(flow_engine 判定與可清項由該案接手;舊稿 flow-boundary-design 已刪除) |
| FR-101 | 2026-09-16 | jedi-issue 大整理後重掃 — 🟡 已開卡待派(母卡 CM-1825、子卡 CM-1826~1828,一次建完連號)。FR-099 把主專案意見回饋與標籤整組搬進套件後,jedi-issue 130→151 檔(38 新、25 改、57 沒動);FR-081 掃的是搬家前版本、其 I2 那 31 檔主專案側已全刪、CM-1630 搬家沒修。只掃有變動的 93 支,三棒:J1 意見回饋全鏈+route 與守門殼(31)→ J2 插件骨架+標籤鏈+4 支 migration+共用(37)→ J3 有改動的整合與附件層回歸(25,決策者裁要掃)。57 支未動沿用 FR-081。主專案接線 core/plugins/issue.py 另棒與 log/asset 接線合併。一次只派一棒。 |
|
| FR-102 | 2026-09-16 | 主專案全模組現況地圖 — 📋 純記錄不派工(卡 CM-1824)。決策者 2026-09-16 要開發新功能前先要一張地貌圖,明確要求只給現況、不給建議(不排優先序、不判輕重緩急)。api/+app/+domain/+infra/ 四層 636 檔/62,442 行,以模組為單位盤完 26 個(卡上估「約 25 個」,差在 identity/common/evidence_classification 這類單層或零行目錄),無跳過、無 ❓ 需查證。分布:實的 14、接線殼 4、殼 1、殘留 2、死的 0,另 5 個是不屬五類的共用設施(readmodel 跨疆界唯讀櫃檯/identity port 實作/common 共用型別,另標 ⬜ 一類並說明理由)。三個數字:主專案只剩 19 張自持表(對照 DEV 庫 169 張,資料層絕大多數已在套件);對外 route 200 條(api/ 199 + core/plugins/remote_agent.py 單掛 1 條,另 7 條被註解不計);oscal(19,996 行)+module_frame(10,951 行)兩支佔總量 49.6%。實查撞到的兩處殘留:api/translate/ git 已零檔案、工作目錄只剩 5 個 .pyc;app/evidence_classification/ 零行 Python、只有兩個與套件位元相同的 JSON(build_release.sh:674-677 已寫明那份是 scripts/evidence/classify/ 原型腳本的輸入、非產品執行期讀)。另抓到 app/report/common/common_utils.py(41 行)全 repo 零呼叫者。三個需另開卡深挖:oscal 與 module_frame 內部真業務與轉接殼混住同一 service 目錄(模組層級單一標籤蓋不住,需逐檔判);associations 三組 mapping service 中兩組的呼叫者只有 DI container 註冊、無業務端 import。🔴 前端四層查法入卡並實跑:api.js 常數/FE 路由/DB ui_routes/非瀏覽器呼叫者——第四層抓到兩支「前三層全空但活著」的:report(服務 bin/report_downloader/ 的 Selenium)與 version(e2e 版本探針+build smoke 探針②+容器探針驗 socketio 模式沒載 REST)。flow_control/flow_engine 只記規模不判定(FR-104 深挖中,避免第二份真相)。文末「怎麼重跑」七段指令全數實跑驗證過(含「數 route 必須用 AST 不用 regex——add_resource( 常換行寫,本棒第一版就因此漏抓 4 條」)。見 README |
relates to FR-100(route 欄與四層查法的前身,report/user_auth_provider/translate 結論直接引用)/FR-104(flow_control/flow_engine 判定歸該案)/FR-099(盤點時五目錄已刪故不在表上)/FR-090/FR-080/FR-069(模組化母源) |
| FR-104 | 2026-09-16 | 流程疆界重新分析(flow_engine+flow_control 兩包逐檔歸屬判定)— ✅ 驗收通過、兩項待裁已裁(卡 CM-1823,一棒做完,只分析不動程式)。取代並刪除 2026-08-31 的 flow-boundary-design.md——FR-069 第四階段抽出兩個套件後,兩包從 226 檔縮到 114 檔/14,350 行,舊稿每個數字都已失效。逐檔實查(語法解析取正反向依賴,非字串比對)判給五類:引擎 57/平台 19/稽核 14/主程式編排 12/還看不準 1(+11 支空檔),每筆附「import 了誰、被誰 import」。30 條對外端點四層查過零死亡(api.js 常數/FE 路由/ui_routes/非瀏覽器呼叫者——第四層抓到 license_readonly_mw.py:116 白名單收了 /flow-engine/flow-templates/validate,拔掉會讓唯讀租戶靜默失效)。🔴 推翻首腦初判一項:workflow_template_snapshot_service(94 行)依賴面乾淨到只有兩行 jedi_flow_engine import,但唯一業務消費者是稽核套件,列待裁不列可做。立即可做兩項:流程範本一族 11 支/801 行歸引擎套件;三支純讀跨模組查詢 1,259 行搬 infra/readmodel/(D-4 已做掉寫入收斂那半,剩搬遷)。要設計才能動四項,最大是 workflow_execution_service(1,321 行,卡在 notification/associations/module_frame 三個未套件化模組)。D-1~D-9 逐項標註:已完成 5(D-1 三分已切/D-3 吃到申報制/D-5 兩支已進 readmodel/D-8① 三支 stub 已刪/D-8② oscal_audit_service 定讞殭屍已刪)、部分完成 3(D-2 拆分未做/D-4 剩搬遷/D-6 殘留 3 行)、裁示已不適用 1(D-7 判「通用」但實際歸了稽核套件,待確認撤銷)。另一待裁是 snapshot service 歸引擎或歸稽核(兩案與後果已列)。證據變化的重要更正:卡上稱 stage_rollback_service 「原判證據失效」只對一半——直接 import 確實不見了,但稽核依賴改走 DI 注入(flow_control_containers.py:370)+route 層 import(stage_rollback_route.py:19),原判成立。見 README |
relates to FR-069(母源,舊稿在該站、D-1~D-9 裁決紀錄已搬入本案)/FR-100(flow_engine 條目指向本案)/FR-102(兩模組只記規模不判定,判定歸本案) |
| FR-105 | 2026-09-16 | oscal 與 module_frame 逐檔分類 — ✅ 三棒完成並驗收(母卡 CM-1838、子卡 CM-1839~1840,一次建完連號)。FR-102 把 26 個模組盤到模組層級後,明講這兩支「單一標籤蓋不住內部差異」——兩支共 244 檔/30,938 行、佔主專案四層一半,內部同時住著主專案真業務與 jedi_oscal_v2 轉接殼,混在同一個 service 目錄。本案產逐檔的圖(真業務/轉接殼/共用設施/死碼/還看不準五類,每筆附依賴證據),只分析不動程式。按模組切兩棒,module_frame(81 檔/10,942 行、45 條 route)與 oscal(163 檔/19,996 行、61 條 route)皆已完成。第 1 棒三個發現:① 真業務比殼多、不是各半——行數比 50.8%(真業務 5,563):35.0%(轉接殼 3,831):14.1%(接線與型別),真業務約為殼的 1.45 倍,FR-102 粗估的「約各半」方向對、比例要修正;② 🔴 沒有兩份真相,卡片的核心懷疑不成立——原以為六支 v2 子物件殼(party/components/inventory/leveraged/system_characteristic/ssp_resources)與 app/oscal/ 同名五支各寫一份欄位對應表,實查發現 oscal 那五支是直接 import module_frame 這邊的 _build_props/_to_dict/ModuleFrame*Service as _XxxMap,五支檔頭皆自陳「完全相同……故直接共用,確保單一真相」,module_frame 是定義處、oscal 是引用者,連 app/flow_control/assessment_plan_app_service.py:57 也在借同一份;③ 零死碼(81 支全過四層查證),但有五個對外不可達的端點——兩個 route 註冊被註解的 Resource(ModuleFramesRoute/ModuleFrameStartRoute,註解標 [FR-038 DEAD-V1|2026-06-18 停用待清理])+三個前端只在被註解掉的程式碼裡呼叫的下載/匯入端點(ModuleFrame.vue:668,672,737),證據已備齊、只記錄不清。🔵 四層查法新增一種誤判形狀:api.js 常數有定義、但呼叫它的前端程式碼整段被註解——光看 grep 命中數會判成「活」,要開檔看前綴。確實有的重複是 Excel 欄位契約約 40 行(9 欄標題/6 個狀態值/一組配色邊框)在 module_frame_template_import_service.py 與 app/oscal/service/ssp_control_impl_import_service.py 各寫一份逐字相同,但抽去哪裡與兩模組疆界綁在一起,列待設計。核對 FR-102 該列五句證據:無一失效,兩句需精確化(1,500 行那支非「全自寫」、有 18 個套件引用作資料來源;「約各半」比例修正)、一句需補充(同型是六支不是三支);另更正派工卡「43 條 route」為 45 條(FR-102 總表 A 原本就寫 45,卡片轉述誤植)。三項待決策者裁:六支殼裡替套件 NOT NULL 欄位補位的「空值哨兵」要不要退回套件解(兩案與後果已列,關鍵未知是 jedi_oscal_v2 有無其他 consumer)/Excel 欄位常數抽去哪/五個不可達端點要不要清。oscal 那一棒三個發現:① 真業務是殼的 2.4 倍(57.5% 真業務 11,494 行:23.8% 轉接殼 4,757:18.1% 接線與型別),比 module_frame 的 1.45 倍更懸殊——它獨佔「把客戶既有文件吃進系統」那條線,domain/oscal/parser/(2,027 行)與 import_diff/(1,384 行)合計 3,411 行零套件引用;② 五支 SSP 子物件殼確認是引用者不是重複實作,兩個模組的判斷對得上,且 SspResources 那一對走的是住在 oscal 側的第三支共用 service(嚴格說是 5+1 對 5+1 不是六對六);③ 六支死碼/126 行全在 api/ 層——一支被註解的 route 檔(oscal_export_route.py,但它背後的 OscalExportAppService 是活的、框架 OSCAL 下載在用,不可一起收)+五支互相用 marshmallow 字串式 Nested 引用成封閉圈的序列化器(grep import 抓不到,且與活著的同功能類別名字只差三個字母 SspSystemCharacteristicResponseSchema vs SystemCharacteristicResponseSchema,是清理地雷;守衛測試白名單那三行的「本卡範圍外未動」是說明沒清、不是說明它們活著)。另抓到兩條註冊了但全前端零呼叫的資源庫端點(詳情/發布——發布是公版治理唯一途徑、風險最高)與三條前端打得到但後端不存在的路徑(/oscal/catalog-controls/<uid>/assessments 是沉默的後備路徑:快取沒命中時拿 404 → 靜默回空陣列 → AO 清單空白且不報錯)。🔵 依賴方向實測:跨模組 import 12 處,9 處是 oscal → module_frame(大模組依賴小模組,與直覺相反),反向只有 3 處——已升為待裁第一題。Excel 欄位契約逐字重複實測約 25 行(非 40 行),但兩邊變數名不一致(HEADER_LABELS vs EXPECTED_HEADERS)比重複本身更麻煩。核對 FR-102 該列五句:無一失效,兩句需精確化(domain/oscal 4,549 行非全是真 domain 資產,實查 3,121 行真業務+1,428 行共用設施;零套件引用的範圍比原句更廣,是整包 import_diff/);卡片問的「三張 job 表有無只寫不讀孤兒」不成立,三張都有寫入者也有讀取者。見 README |
relates to FR-102(兩模組需另開卡的結論由本案接手,該列證據已逐句核對)/FR-100(四層查法前身)/FR-104(module_frame BPMN 那兩支要等流程疆界結論)/FR-080(終局形狀定義)/FR-069/FR-038(v2 重寫母源) |
| FR-106 | 2026-09-16 | SSP 對應層歸位 oscal(反轉 module_frame 與 oscal 的依賴方向)— ⏸️ 設計稿留存、決策者裁先不動、未開卡。FR-105 兩棒查出 SSP 子物件對應表、SSP Excel 範本產生器(1,656 行)住在 module_frame 純因資源庫先做,導致 SSP 本家 oscal 反向依賴 module_frame(app 層 6 檔+DI 6 處)。稿子給出反轉方案(約 36 檔、邏輯零改動、守衛擋回頭)與四個被排除的方案(新開共用模組/維持現狀/塞 common/推進套件)。決策者 2026-09-16 裁「與主專案牽連太多,後續釐清再處理」——理由:反轉只解模組間方向,不解三支千行大檔殼與業務混住的糾纏,那要等新功能帶真實需求回頭。見 design |
relates to FR-105(實查來源)/FR-080(終局形狀)/FR-038(v2 對應表起源) |
| FR-107 | 2026-09-17 | 證據自動分類 2.0(儲存後端無關的暫存區 → 分類 → 確認 → 歸檔進任務)— 🟢 16/31 張子任務卡驗收通過,3 張派出中(T-3.4/T-4.1/T-5.3b);D13 原廠 AI 金鑰裁定並落地(T-5.5)(母卡 CM-1843、子需求卡 CM-1844~1849、子任務卡 CM-1850~1871+1877~1879,共 32 張連號)。把分類線從 Google Drive 搬回系統儲存後端:使用者上傳到掛輪次的暫存批次 → AI 分類 → 審閱確認 → 檔案搬進對應任務寫 job_evidences;套件開 IEvidenceStorage port、容器不再自己連 Drive/DB;框架知識去硬編碼(catalog part_id+新表 classification_profiles);三個 AI 功能(小幫手/Dashboard/分類)統一金鑰解析+原廠鑰裝機寫入。D1–D13 已裁(D11:新功能全進既有套件 jedi-evidence-classification;D12:多供應商 AI;D13:原廠 AI 金鑰統一供應)、六棒 25 張子任務卡外加 1 張 mockup 卡;硬約束 upload_files 補租戶/擁有者/RLS。見 design/discussion |
relates to FR-030(Drive 版自動分類母源)/FR-031(分類報表,資料來源改讀)/FR-065(落地版無 Drive 的觸發)/FR-042(upload_files storage_scope) |
| FR-108 | 2026-09-16 | 弱點掃描整合套件(jedi-detection)資安掃描 — 🟡 已開卡待派(母卡 CM-1872、子卡 CM-1873~1876,一次建完連號)。決策者 2026-09-16 指定優先開這支。套件正式碼 160 檔(總表原寫 251 是含測試碼,已更正),扣 R2b 那 11 支 agent 檔,重縮三棒 83 檔(決策者裁「檔太多」,剔 66 支無邏輯檔、D4 作廢併 D1)、按業務鏈垂直切:D1 工具目錄+租戶憑證+守門殼+插件骨架與 migration(36)→ D3 執行編排(17)→ D2 掃描基準全鏈(30)。CM-1595 明文帳密鏈的終點在這支;四件高風險動作(帳密解密下發/壓縮檔解析/代抓外部網址/跑 cinc-auditor)各有自陳界線的防護模組,逐道驗。主專案接線 14 檔另棒。 | |
| FR-109 | 2026-09-17 | 問卷套件(jedi-survey)資安掃描 — 🟡 已開卡待派(母卡 CM-1880、子卡 CM-1881~1882)。決策者 2026-09-17 指定。套件正式碼 162 檔,剔 81 支無邏輯檔後兩棒 81 檔、按「填答/建題」切:V2 填答全鏈(31,先派,主目的是驗 2026-07 FR-048 補的「只有被指派者或專案管理者能改填答」有沒有涵蓋所有入口——首腦初看讀取類端點全無歸屬守門)→ V1 建題全鏈+守門殼與插件(50)。15 張表 RLS 靠 join 反查有租戶欄的表,鏈斷即全開,兩棒都驗。主專案接線 10 檔另棒。 | |
| FR-110 | 2026-09-17 | Google Drive 應用程式設定(OAuth 憑證從環境變數搬進 UI)— 🟢 已完成並 push(2026-09-18,BE 20 支+FE 7 支;基線已重產)。原本要開通 Drive 整合得有人登進主機改 .env 再重啟服務(落地版客戶端沒有這條動線),且填錯的唯一症狀是使用者按授權時撞 Google 的英文錯誤頁。現在改成新頁「Google Drive 應用程式設定」(/system/drive-app-config,掛系統設定群組 pid=47/sort=39):client_id/client_secret/系統對外網址畫面手填,回呼網址與通知用對外網址由對外網址推導、唯讀顯示+複製鈕(進階區可覆寫),密鑰用既有 DRIVE_TOKEN_ENCRYPTION_KEY 加密落庫、空鑰匙直接拋錯無明文路徑,改完不必重啟服務。機制照抄 FR-107 T-5.5 的 AI 服務設定(遮罩回 is_set、缺的密鑰從舊值補回、clear_client_secret: true 才清除、能力點沿用 storage-config.{read,update} 不新開以免漏 seed、能力點之後再套一層 require_platform_admin())。「驗證憑證」按鈕拿假授權碼打 Google 換票端點三態判定(invalid_client=憑證錯、invalid_grant=憑證對、連不上=外網不通),三態一律 HTTP 200;憑證正確時附提醒「回呼網址仍需自己貼進 Google 後台」(換票不比對它)。租戶端「雲端空間整合」頁在平台未設定時停用連接鈕並留住提示(GRC_412053,不彈 toast)。資料庫與設定檔是整組切換不逐欄位混用;裝機不 seed(「資料庫有值=有人設過」才是乾淨判準)。2026-09-18 決策者手測後追加三張卡全數 Done:CM-1912 暴露既有潛伏 bug——建 Drive 資料夾骨架用 ThreadPoolExecutor 扇出,子執行緒不繼承 ContextVar 身分,session_scope() fail-closed 後 RLS 把 tenant_drive_integrations 整張擋成 0 列,於是只建出最上兩層、底下全 0 個而背景工作標成成功(改成每個 task 各 copy_context().run() 帶身分,整批全滅改記 FAILED 不假裝成功);CM-1913 補三個「沒訊息或只有 Google 英文原文」的缺口——即時通知登記失敗不再 rollback 掉整個授權(改記白話降級訊息進 last_sync_error 並顯示在整合卡片,因為沒有它定時輪詢照樣同步)、對外網址非 https 在設定頁當場警告但不擋存檔(內網合法降級)、兩個進階覆寫欄位前後端各擋一層格式(SYSTEM_CONFIG_400002/400003),另補手冊「在 Google 取憑證」六步(同意畫面測試中要加測試使用者/回呼網址逐字一樣/登記後要等幾分鐘生效/密鑰只顯示一次);CM-1940 新增唯讀端點 GET /integrations/google-drive/projects/<uid>/folders?round_uid=+專案總覽與專案規劃頁各一顆入口按鈕(有輪次資料夾開它、否則退開專案資料夾、都沒有就不顯示),按鈕由決策者定名「證據雲端資料夾」而非「開啟 Google Drive」(供應商中性,日後換雲端硬碟不必改文案)。出貨基線已重產(8cc99148,與 FR-071 一支同批)。剩餘 follow-up 兩項:error code 鏡像測試紅(主專案比 jedi_compliance_audit 多三碼,裁下次發套件補)/離線 Drive 分類腳本已停用待 FR-107 舊線一併刪。見 SUMMARY、頁面 SPEC、design、analysis |
relates to FR-070(白話需求前身,AI 半邊已隨 FR-107 T-5.5 落地)/FR-016(Drive 整合地基)/FR-107 T-5.5(AI 金鑰 DB 化先例,本案照抄機制)/FR-052 |
| FR-111 | 2026-09-18 | 證據自動分類套件(jedi-evidence-classification)資安掃描 — 🟢 arc 收口(2026-09-20,五棒全掃完驗收,淨新增 8 條資安 1 高 4 中 3 低+4 條功能 bug;未修的已歸 1.21.1 hotfix 母卡 CM-2289)。風險集中在待刪的舊 Drive 線:預覽端點任何登入帳號填雲端硬碟檔案編號就能讀客戶整個硬碟(高,總表第 108)+同鏈三條中等,刪 api/routing.py:40-56 三支路由一次消四條;容器端金鑰走 docker run 命令列與無資源上限皆輕微(落地版後端刻意沒裝 docker、分類功能跑不到);FR-107 寫的新批次線把舊線的坑全避開。五項待裁見總表 §7。SUMMARY:handoff/2026-09-20-FR-111-SUMMARY.md。(盤點卡 CM-1945、母卡 CM-1946、子卡 CM-1947~1951)。決策者 2026-09-18 裁 FR-107/FR-110 收口後排掃。21 支裡唯一同時跑外部程式(docker 容器)、連客戶雲端硬碟、用 AI 金鑰的一支。套件正式碼 97 檔 10,450 行,剔 56 支無邏輯檔後五棒 41 檔 7,849 行、每棒 ≤2,000 行(D3 五次零產出換來的硬上限):E1 容器執行鏈(7 檔,先派——金鑰走 docker run 命令列、落地紀錄只遮命令列不遮 stderr)→ E2 批次分類主幹(2 檔 1,900 行,逼近上限)→ E3 舊 Drive 線(4 檔,觸發端點吃前端給的資料夾 ID、job 狀態無守門)→ E4 設定與插件殼(16 檔)→ E5 邊界層(12 檔)。主專案接線 5 檔約 1,300 行另棒(金鑰解析鏈本體在那邊)。全機一次一支掃描,與 jedi-detection D3 輪替。 |
relates to FR-107/FR-110/FR-094/FR-048/FR-086/FR-077 |
| FR-112 | 2026-09-19 | 專案規劃頁新增任務與平行流程 — 🟢 完成並 push(2026-09-20,24 卡 Done,review 4C/6I 已修,八支套件已發版)。跨四 repo(BE/FE/jedi-flow-engine/test)、新增 6 支 error code、e2e 新情境 12 條、無 DB migration;2026-09-20 arc-review(CM-1977,review 報告)找出 4 Critical/6 Important(共同病因「兩入口只改一邊」)已全數修完(CM-1978/1979/1980),套件已發版、三 repo 已 merge push,詳見 收尾 SUMMARY §10。要替一個查核項目多開一個任務,目前唯一動線是打開流程圖編輯器、從工具列拖方塊、手動接線、填一堆屬性——那是工程師的工具,PM 不該被要求會用;而任務資料同時存在資料庫與流程圖 XML 兩處,編輯器存檔會逐節點打更新蓋掉規劃頁設好的問卷與審查旗標(程式裡那幾條「這欄不要蓋」的防禦註解就是病徵)。本案把新增/刪除任務放回專案規劃頁,新任務預設掛成平行分支(誰先做都行、全部做完該查核項目才算過);流程圖降為只管走向——圖上只有「拓樸」與「指回哪一筆任務的編號」是真的,名稱是後端單向寫的顯示副本,其餘 camunda 屬性不再寫也不再讀(舊屬性不清、讀時忽略,但寫入端收斂成只寫名稱,否則永遠不會自然凋零)。編輯器屬性面板只留名稱(決策者原話「回歸最簡單就好,目前的 UI 設計不是很好用,之後再來優化」,UI 優化列延伸項)。刪除兩個入口對稱:規劃頁按刪除與編輯器刪方塊存檔都會真的刪掉任務,共用同一支 delete_job()(它負責清五張軟參照關聯表,另寫一套必定漏刪)——因此「XML 少了任務編號」判定為刪除意圖而非孤兒,存檔端點改成三向 diff(無編號的新節點建任務/消失的編號刪任務/其餘只更新拓樸)。新增與刪除都只在規劃期開放,凍結後按鈕停用並顯示原因。🔴 連帶修一個既有引擎缺口:合流閘道不等兄弟分支就放行——完成第一條平行分支,合流後面的任務立刻跳成進行中,同一份寫法有兩個副本(complete_job() 與 complete_main_workflow_job())兩處都修,拓樸判定函式放 jedi-flow-engine。現況每個查核項目只有一個任務所以沒人踩到,本案讓平行變成預設樣貌就會浮現。另修兩處平行結構下的誤判:新任務初始狀態(現行邏輯會讓第二個以後的平行任務變 TODO 排隊)與「可不可以退回」(只看下一批第 0 筆)。開工前必驗:輪次推進/回退讀的流程圖與查核項目底下的收證據流程不是同一張,若共用則整案範圍重估。範圍排除流程範本管理頁。見 FR-112 站首頁、design、discussion |
relates to FR-038(任務與 BPMN 節點對應地基)/FR-069(綁定表軟參照,刪除清理責任在程式)/FR-110(凍結時按鈕停用+留住提示的做法)/FR-048(專案角色守門) |
| FR-113 | 2026-09-21 | jedi-oscal-v2 主專案側接線資安掃描 — ✅ 全掃完,新發現已進總表(母卡 CM-2000、子卡 CM-2001~2009 一次建完連號,切棒修訂時另建 CM-2010=O3b)。合規資料(系統安全計畫 SSP/控制項實作/合規框架)底層是外部套件 jedi-oscal-v2,主專案這邊「接線」的程式從未被任何 arc 掃過(網址入口 → 商業邏輯 → 資料庫查詢)。排第一順位的理由:①總表第 67 項已順手掃到這裡有問題(租戶可改掉原廠公版範本),指向的 resource_library_app_service.py 還有另外 8 段手寫 SQL 沒人看過;②合規資料是產品本體;③零覆蓋。範圍界定 160 檔,其中 92 檔進掃描、68 檔為資料結構宣告(空 __init__.py、ORM model、entity 介面、純格式定義)不排入掃描;十棒合計 92 檔/17,224 行(逐檔 wc -l 實算、十棒無重複檔),按業務鏈垂直切:O2 資源庫與匯出(11 檔,先派——全批唯一確認零守門的檔 530 行+9 段 sa.text,且含唯一呼叫外部程式 LibreOffice 的檔)→ O1 控制項實作+全系統唯一一支 SSP 權限判斷程式 common/authz/ssp.py(6 檔,結論是後面各棒的判斷基準)→ O3a/O3b/O4 外部輸入正門(5/7/9 檔,可換序)→ O9 接線總裝(18 檔,驗證依賴注入有沒有接對=前面各棒結論成不成立)→ O5/O6 子物件與比對引擎(15/6 檔)→ O8a/O8b 合規框架(6/9 檔,守得最嚴期待值最低)。🔴 推翻總表的錯誤前提:總表 §0.5 寫「122 支入口完全沒有權限檢查」不成立——入口實數 89 支,且 SSP 線權限是有守的、守在下一層(app service 層 require_manager 33 次+require_participant 21 次=54 次,框架線另有 require_platform_admin 21 次),這是 CLAUDE.md 明文允許的資源域守門做法。確認零守門的只有 resource_library_app_service.py 與 module_frame_template_ssp_route.py 兩支。卡片一律寫成「逐支公開方法核對守門是否齊全」,照抄總表會掃出整棒誤報。本批不含:module_frame 81 檔(風險型態不同,另立獨立棒)、Word 內容抽取器 7 檔 2,868 行(純解析無權限議題,併套件本體那批)、套件本體 364 檔(另 FR)。⚠️ 每棒 ≤2,000 行是硬上限(D3 五次零產出換來):原 O3(3,118 行)與 O4(2,570 行)超標,處置是把兩條匯入線共用的接縫檔 _common.py(620 行)從兩棒移出改掛 O9,O3 再拆成 O3a 上傳入口與確認流程(5 檔/1,460 行,權限題)與 O3b Excel 內容解析(7 檔/1,047 行,惡意檔案題)——拆點照題目性質切,兩種題目檢查清單不同。修訂後十棒實測全部 ≤2,000 行,唯 O9 因接手 _common.py 為 2,505 行、排序在後派工前再切。盤點檔 scan-inventory.md(寫的是拆棒前的九棒版,範圍以卡片為準)。 |
relates to FR-095 H1(總表第 67 項的來源)/FR-048(資源域守門放 app service 層的規範)/FR-038(2A 遺留的註解路由與 scoped 匯入不對稱)/FR-111・FR-108・FR-109(同期套件掃描 arc) |
| FR-114 | 2026-09-21 | 資安修正派工計畫 — ✅ 已出貨 1.21.0(2026-09-28,190/188 STG/189 POC)(母卡 CM-2019;收口見 SUMMARY)。把資安檢視總報告 docs/security-report/SUMMARY.md 的 145 件問題翻成派工單:121 件要動手,拆成 46 張卡、六批(1 權限地基 9 張/2 只驗登入不檢查歸屬 10 張/3 刪除 5 張/4 憑證殘留 4 張+沿用 CM-1998/5 設定與信任鏈 18 張/6 資料庫牆本棒不開)。第 1、3、4、5 批可立即開、第 2 批等第 1 批合回+套件發版。一個 worktree 一張卡;套件 monorepo 開 worktree 後 BE pyproject.toml 改 path dependency 指過去、不 commit。總覽 dispatch-plan.md,逐卡細節在 batches/plan-b*.md,材料(SUMMARY 列+模組頁列+掃描總表列機械抽取)在 batches/material-b*.md。41 張舊修正卡已作廢(掃描總表 §2.2/§2.3)。 |
relates to 資安檢視總報告(docs/security-report/)/security-scan-consolidated 掃描總表/FR-107.6(M07 舊線退役 CM-1849) |
| FR-115 | 2026-09-23 | 主專案接線補掃(問卷/檢測/日誌/資產/議題五支套件在主專案側的接線程式)— ✅ 八棒全收(2026-09-24)(母卡 CM-2086,W1~W7 盤點範圍 46 檔+W8 補掃 4 檔)。五支套件本體已掃完,主專案側接線層先前全部沒掃;交接文件寫「三支小接線合一棒」,首腦按 import 實數至少 34 檔/12,400 行、是 6~8 棒的量,故先派盤點員切棒再開掃描子卡。只掃不修。 | |
| FR-116 | 2026-09-23 | jedi-compliance-audit 全掃(套件本體 176 檔/13,865 行+主專案側接線 28 檔/11,557 行)— ✅ 九棒全收(2026-09-24)(母卡 CM-2088,子卡 CM-2097~2105)。淨新增 8 條(0 高 2 中 6 低)+第 66 項升高+第 133 項修法前提推翻。總表 §0.5「完全沒碰」三支之一;FR-113 O6 已證實其刪除方法查詢條件只有編號沒有父層範圍(第 118/119 項根因在套件側),套件與接線要配對切。只掃不修。 | |
| FR-117 | 2026-09-24 | 出貨基線改依套件產生——02-schema.sql 只留主專案的表,套件的表由套件 migration 從零建出(接續 FR-093 預設資料歸套件)— ⬜ 未開始,決策者裁 1.21.0 後再排。前提缺口:多數套件 migration 缺最初建表語法 |
|
| FR-118 | 2026-09-24 | jedi-oscal-v2 套件本體全掃(363 檔/15,852 行+主專案側 Word 解析器 7 檔/2,946 行)— ✅ 八棒全收(2026-09-24)(母卡 CM-2122,子卡 CM-2124~2131)。淨新增資安 7 條(0 高 1 中 6 低)+§3.2 兩條;「XML 攻擊」與「同 uuid 兩份 SSP」兩個交接假設推翻。總表 §0.5 待掃第 4 順位、21 支裡最後一支完全沒碰過的;盤點查證「XML 攻擊」不成立,風險形狀是「服務層開放只認編號的讀改刪、底下 45 張表零隔離」與檔案解析安全。只掃不修。 | |
| FR-119 | 2026-09-24 | 資安掃描線收口(主專案未掃清單重數與切棒/§7 待裁裁決稿/security-report 回寫/打包交修正線)— ✅ 四棒全收(母卡 CM-2139;盤點 CM-2140、裁決稿 CM-2146、打包 CM-2150、回寫 CM-2151 皆 Done)。決策者十九件全裁完,裁定表 decision-draft.md;交修正線清單 handoff-to-fix-line.md。套件線 FR-116/FR-118 收完後的跨線收口;決策者裁套件先做完、晚上視盤點掃主專案。 |
|
| FR-120 | 2026-09-25 | 主專案未掃程式全掃——119 支判斷邏輯切 U1~U12 十二棒+U13a/U13b DI 專掃+1 張 DI 腳本實作卡,共 16 張卡(母卡+15 子卡)— ✅ 全掃完,新發現已進總表(母卡 CM-2152、子卡 CM-2153~2167,一次建完連號)。決策者裁與修正線並行;只掃不修。 | relates to FR-119(範圍與切棒依其盤點檔與裁決稿) |
| FR-121 | 2026-09-27 | 全庫 63 表 140 欄無時區時間欄位改 timestamptz,資料庫統一存 UTC(FR-114 b3 總測 #16 拆出,決策者裁進 b4)— ✅ 已出貨 1.21.0(2026-09-28)(母卡 CM-2253、子卡 CM-2254~2259 皆 Done)。 | relates to FR-114 |
| FR-122 | 2026-09-28 | 三支 AI 功能改走共用 AI 閘道(入口/出口守門、稽核)+不可信檔案改在無金鑰不出網的沙箱容器拆解+長工作搬 worker;資安先解、成本第三階段 — ✅ 已出貨 1.22.0(2026-09-30,188 STG/189 POC/190 三環境同包;收口見 SUMMARY)(母卡 CM-2293 Done) | |
| FR-123 | 2026-09-28 | 1.21.1 hotfix:資安總表沒卡未修 9 條+installer 升級鏈三缺口+AI 資安議題預留 — 🟡 母卡已開待裁第一批(母卡 CM-2289)。 | relates to FR-114/FR-122 |
前 13 個(FR-001 ~ FR-013)的提出月份為推估值:它們同屬 2026-04-01 一次性
docs/目錄重組 commit(a098cfa5)遷入,無精確日期,月份依文件內部日期 + 邏輯分組推得。