跳轉到

我的任務(My Tasks,受稽方執行)

功能群:稽核執行|輪次狀態機與 AP→AR→POA&M 資料模型先讀 功能群總覽

事實基準:2026-07-05 從 FE / BE code 掃出(FR-038 v2 + 證據蒐集任務執行);API schema 逐條對照 api/grc/serializers/job.pyapi/grc/serializers/job_batch_complete.pyapp/participant/service/task_assignee_service.py

變更紀錄

日期 FR 變更
2026-08-29 CM-1425 失敗執行紀錄可從 UI 刪除 + 卡住的執行自動收斂:①執行紀錄失敗列出現刪除鈕(確認框),整組全失敗時卡片層另有「刪除整組」;只准刪 failed——succeeded 掛著報告與證據(刪了證據鏈斷)、running/scheduled 要先取消、cancelled 是有意義的操作軌跡,成功項不出鈕且直打 API 回 409016;刪除寫稽核事件(6120/6121)。刪單筆不重算群組彙總狀態(刻意:刪掉一筆失敗不代表這次執行變成功,重算會把「四台掛三台」改寫成部分失敗)。②背景排程每 15 分鐘檢查,running/scheduled 超過 DETECTION_EXECUTION_TIMEOUT_HOURS(預設 4 小時)且 agent 無回報 → 自動判 failed(訊息註明逾時無回報)並重算 group,收斂後即可被①刪除。詳見 §11.2
2026-08-26 FR-067(驗收回饋,v1.16.0 後續補項,歸下版) 執行抽屜三項顯示修正:①執行紀錄的掃描目標改印使用者原始寫法+BE 算好的真實台數192.168.50.1-5(5 台)而非 5 個 IP 並排;來源=派工當下快照 _scan_target_spec,透傳欄位無快照就地算,存量舊紀錄不重跑也正確),列上講真正被掃的欄位(有 targets 講它——nmap 的 hosts 是跳板機不是掃描目標,判準看資料不看工具清單)、詳情長 label 改短標籤+ⓘ tooltip;②「檢測設定」卡多組時改逐組分塊(跨列「/」併陳在 SonarQube 混模式講不出哪列是哪列;單組版型不變),上傳槽與擋門訊息改標「第 N 組(辨識參數)」(組號用全域序號);③單組重跑前置放寬——群組還在跑也可重跑失敗組(只看該組自己最新一筆是否 failed/cancelled,409012 退役無 raiser);未掃到警示字配色改 theme-aware token(亮色主題白底可讀)。詳見 §11.1(CM-1395/1396/1397)
2026-08-25 FR-067.8 源碼包上傳改成「每個 upload 列一個檔案槽」:任務設定改每列自足後(見任務配置),同一任務可有兩個 upload 列各掃各的包(前後端各一包是典型用法),單槽「一個任務一包」表達不了。抽屜上傳區改逐 upload 列各一槽(非 upload 列不出現)、各列各自 sticky、擋門逐列且 tooltip 指出是哪一列缺檔、上傳中狀態 per 列。execute 改送 source_files{分派列: {uid}}),只帶這次剛換過檔的列。另抽屜四處原本讀任務層掃描參數(上傳模式判定、檢測設定顯示、執行主機/掃描目標清單)改讀各分派列跨列彙整(值不同併陳、主機清單取聯集),零列時退回任務層走存量相容——不改的話新任務那幾處會全部空白且不報錯,看起來像「這個任務沒設定」。詳見 §11.1
2026-08-25 FR-067 檢測執行紀錄群組化(多 Agent 分派):執行紀錄 API 改回兩層形狀(群組 → 各台執行紀錄),抽屜以 group 卡片呈現——彙總徽章(succeeded 綠/partial_failed 黃沿 CM-952 語彙/failed 紅/running 動畫/「⏱ 排程中」中性色)、每 assignment 一列(agent 名稱/目標/狀態/報告)、失敗列「重跑」鈕、running 列「取消」鈕、卡片層「整組取消」、排程中的組「立即開始」鈕、重跑歷史收合;legacy 舊資料單筆自成一組(is_legacy,形狀一致不分叉);既有 job 層取消端點改委派整組取消(best-effort,全部不可達才 409);彙總通知改收口時一封(每台一列,取代每筆一封);掃描失敗訊息帶出 stderr(agent 0.2.29,原本冒號後一片空白)。詳見 §11.1「執行紀錄群組化」
2026-08-01 FR-058.7 SonarQube 上傳模式的執行時上傳scan_mode=upload 的檢測任務,抽屜執行區出現源碼壓縮包上傳區(.zip/.tar/.tar.gz/.tgz、預設 100MB 上限)——首次執行必須上傳(無檔不給按執行)、已上傳檔案 sticky 保留供重掃沿用(顯示「目前檔案:xxx.zip」,直接按執行=掃同一包,換版再上傳替換、舊檔保留);execute 請求只送 file uid,檔名等 metadata 由 BE 從 upload_files 權威取回;執行紀錄 scan_params 快照含 source_file: {uid, file_name} 顯示檔名非裸 UUID。檢測掃描完成通知加厚(D34):內容擴為九項(專案/控制項群組/控制項/AO/任務/工具/掃描設定/時間/狀態)+報告檔名,失敗也通知(含錯誤訊息、收件人與成功相同),管道補齊 Email/Discord/Telegram 三管(見 §11.1)
2026-08-01 FR-059 檢測任務抽屜的 profile 顯示接掃描設定檔庫:param_schema 宣告 options_source: "profile_library" 的欄位(CINC Auditor / GCB 的 profile)值可能是 profile:<uid> 庫內參照,抽屜另向 profile menu API 取「值→顯示名」對照,執行紀錄與任務資訊摘要卡顯示設定檔名稱而非裸參照;對照拿不到(或參照已停用不在 menu)退回顯示原值,不擋畫面(見 §11.1)。設定檔維護見 掃描設定檔管理
2026-07-31 FR-058 執行紀錄新增取消執行中掃描的獨立入口(POST /detection-tools/jobs/{job_uid}/cancel,僅 running 那筆顯示;按鈕刻意縮小一級並與 info icon 對調位置);任務資訊摘要卡與執行詳情視窗分開顯示「執行主機」與「掃描目標」(Nmap 兩者不同——Agent 登入執行主機再掃目標網段),標題一律沿用 BE param_schema 的 label 不在 FE 寫死
2026-07-29 FR-057 執行歷史回應擴充人事時地物 + 多檔報告:新增 reports(該次執行的所有報告清單,OpenSCAP 逐台一份)、detection_tool_namescan_params(憑證已剝除的快照)、created_user/created_user_namereport_file_uid 單值欄位保留供舊讀取端相容,FE 已改讀 reports(見 §11.1)
2026-07-27 FR-056 新增 detection_tool 任務類型:抽屜出現執行紀錄區塊(可收合、最新在上、running/最新失敗預設展開);重新執行依有無執行中紀錄分岔(無→直接派工,有→確認框→真中斷→才派新工單,見 §11);PDF 證據 + 發現項目統計;cancelled 執行狀態 Tag
2026-07-24 v1.10.0 任務清單加輪次欄(round_no/round_type/round_uid,NULL fallback 顯示第 1 輪)+ 輪次篩選(CM-846);分段按鈕視覺改 outline 統一

1. 功能描述

我的任務是受稽方執行人員的跨專案任務收件匣:列出當前使用者被指派的證據蒐集任務(prep-job,由專案規劃頁的任務指派 + 開始執行任務產生),提供上傳證據 / 填問卷 / 留言 / 完成任務的執行面。與 AP/AR/POA&M 頁不同,本頁不綁單一輪次階段,而是以任務狀態(TODO / PROCESSING / COMPLETED)為 gate,跨所有專案彙整當前使用者的待辦。

主要使用者:任務被指派人(assignee,受稽方);覆核人(reviewer / is_approver)另有退回權。

角色速覽(本頁角色是任務層,不是專案層的 manager/auditor/viewer):

角色 一句話
assignee 任務被指派人 — 受稽方,執行任務、上傳證據、完成
reviewer 覆核人(is_approver)— 可退回任務要求補件

任務的來源與文案真相在專案規劃頁的 prep-job(BPMN userTask 衍生,見 專案規劃頁);本頁是其執行下游。PM 在規劃頁「開始執行任務」把任務 TODO→PROCESSING 後,任務才出現在受稽方的收件匣可執行。

1.1 功能總覽(本頁全部功能)

# 功能 說明 位置 詳述
1 任務清單(分頁 / 排序) 跨專案彙整當前使用者被指派任務;欄:專案 / 群組·控制項 / AO / 任務名 / 類型 / 狀態 / 輪次(round_no+round_type,NULL fallback「第 1 輪」) 左清單面板(55%) §6.2
2 關鍵字搜尋 任務名關鍵字 清單工具列 §6.2
3 狀態篩選 全部 / TODO / PROCESSING / COMPLETED(預設 PROCESSING) 清單工具列 §4
4 專案篩選 依專案下拉過濾 清單工具列 §6.1
4a 輪次篩選(v1.10.0) round_uid 精確過濾(CM-846,多輪次易混淆) 清單工具列 §6.2
5 批次完成 多選可完成任務一鍵批次完成(逐專案分送) 清單工具列(選取後出現) UC-MT-02
6 任務明細抽屜 點列開右抽屜(45%):描述 / 指南 / 指派 / 部門 / 設備 / 問卷 / 證據 / 連結 / 留言 右抽屜 JobExecutionDrawer UC-MT-01
7 上傳檔案證據 拖放 / 瀏覽上傳檔案(FILE 證據),可預覽 / 刪除 抽屜證據區 UC-MT-01
8 新增 / 編輯連結證據 標題 + URL(LINK 證據)增改刪 抽屜連結區 UC-MT-03
9 填問卷 開問卷填寫頁(survey-v2-fill,新分頁);狀態顯示(0 TODO…9 完成) 抽屜問卷區 §11
10 留言 任務留言增改刪(作者本人可改刪) 抽屜留言區 UC-MT-04
11 完成任務 就緒後完成(general 需 ≥1 證據;survey 需全問卷完成) 抽屜底部按鈕 UC-MT-01
12 退回任務 覆核人(reviewer)退回任務(需理由) 抽屜底部按鈕(reviewer 模式) UC-MT-05
13 檢測工具執行(FR-056) 任務類型為 detection_tool 時:抽屜顯示「開始執行 / 重新執行」+ 執行歷史區塊(可收合、狀態/發現項目統計/報告下載)+ 任務資訊摘要卡(工具 / profile / 完成模式 / 執行主機與掃描目標分開列 Tag,FR-058);SonarQube scan_mode=upload 任務另有源碼壓縮包上傳區(首次必上傳、重掃可沿用,FR-058.7) 抽屜「檢測設定」+「執行紀錄」區塊 §11.1
14 取消執行中的掃描(FR-058) 執行紀錄中 status='running' 的那筆出現「取消執行」按鈕 → 確認 → 直推 Agent 真中斷,成功才標記 cancelled 執行紀錄列(僅 running 且 canEdit §11.1
15 刪除失敗的執行紀錄(CM-1425) 失敗列出現刪除鈕(確認框);整組全失敗時卡片層另有「刪除整組」。只有 failed 可刪,成功/執行中/已取消不出鈕 執行紀錄列 / 群組卡片 §11.2
16 逾時執行自動收斂(CM-1425) 背景排程每 15 分鐘把「卡住超過 4 小時且 agent 無回報」的執行判為 failed,收斂後即可刪除 (背景,無 UI 入口) §11.2

UC(§2)展開本頁所有具實質後端寫入邏輯的功能:單任務執行完成(含上傳 FILE 證據,1/7/11)、批次完成(5)、連結證據增改刪(8)、任務留言(10)、覆核人退回(12)。純顯示 / 導覽類(1 清單、2 搜尋、3/4 篩選)見 §5 / §6.2;填問卷(9)另有所屬頁面(開 survey-v2-fill 新分頁填寫,本頁只顯示狀態並作為完成 gate,見 §11),於此只交叉連結不重複;檢測工具執行(13)另有獨立編排鏈路(非 flow-engine complete,見 §11),本頁只交叉連結不重複。

2. Use Case

角色速覽(本頁角色是任務層,不是專案層的 manager/auditor/viewer):

角色 一句話
assignee 任務被指派人 — 受稽方,執行任務、上傳證據、完成
reviewer 覆核人(is_approver)— 可退回任務要求補件

流程圖視覺慣例:菱形 = 判斷、橘底 = 例外/擋下、紅框 = 錯誤(標 error code)、綠框 = 成功終點、虛線 = 可選路徑。

UC-MT-01 執行並完成單一任務

項目 內容
角色 assignee
前置條件 任務狀態 = PROCESSING(PM 已在規劃頁「開始執行任務」);為任務指派人
產出 / 後置條件 證據寫 compliance.job_evidences;就緒後 complete → job_executions.status COMPLETED(走 flow-engine)

UC-MT-01 流程:開抽屜 → 上傳證據 / 填問卷 → 就緒檢查(general 需證據 / survey 需全完成)→ 完成走 flow-engine complete

UC-MT-02 批次完成任務

項目 內容
角色 assignee
前置條件 多個 PROCESSING 任務皆就緒(可完成才可勾選)
產出 / 後置條件 逐專案分送批次完成;per-job 成功 / 失敗回報(NO_EVIDENCE / SURVEY_INCOMPLETE);統一批次通知

UC-MT-02 流程:勾選就緒任務 → 批次完成 dialog → 逐專案分送 → per-job 就緒複驗 → 結果摘要

項目 內容
角色 assignee
前置條件 任務狀態 = PROCESSING 且為指派人(COMPLETED 唯讀)
產出 / 後置條件 compliance.job_evidences 新增 / 更新 / 刪除 LINK 型(標題 + URL);attachment_count 反映(general 就緒判定)

UC-MT-03 流程:抽屜連結區填標題+URL → 新增 POST /job-evidence(LINK)/ 編輯 PUT / 刪除 DELETE /job-evidence/{uid} → job_evidences 更新

UC-MT-04 任務留言增改刪

項目 內容
角色 assignee(新增);留言作者本人(修改 / 刪除)
前置條件 開任務明細抽屜留言區
產出 / 後置條件 compliance.job_execution_comments 新增 / 更新 / 刪除;修改與刪除限作者本人

UC-MT-04 流程:抽屜留言區 → 新增 POST comments / 本人可修改 PUT / 刪除 DELETE comment → job_execution_comments 更新

UC-MT-05 覆核人退回任務

項目 內容
角色 reviewer(覆核人,isReviewer 由專案 participant role=reviewer 決定,FE 判定顯示退回鈕)
前置條件 覆核模式;填退回理由
產出 / 後置條件 job_executions.status 回退 PROCESSING(走 flow-engine revert,BPMN userTask 回退)

UC-MT-05 流程:reviewer 覆核模式 → 填退回理由 → POST /flow-engine/task/revert/{templateJobId} → BPMN 回退、任務回 PROCESSING

3. 權限矩陣

本頁以「任務指派關係」為權限基礎(非專案層角色):

操作 FE 判定 BE 強制 BE 檢查位置
讀我的任務清單 登入即可(清單本身即過濾成當前使用者) user_id 查使用者任務佇列(僅回自己被指派的) app/participant/service/task_assignee_service.py::list_my_grc_jobs
上傳證據 / 留言 / 完成 任務在 PROCESSING 且為指派人 走 job / flow-engine service(任務層) app/grc/service/job_*
退回任務 isReviewer(專案 participant role=reviewer,FE 判定) flow-engine revert flow-engine
批次完成 只勾選 canComplete() 的任務 per-job 就緒複驗(NO_EVIDENCE / SURVEY_INCOMPLETE) app/grc/service/job_batch_complete_service.py:30

本頁清單天然過濾成「當前使用者被指派」,故無專案角色守門;權限邊界在「任務是否指派給你」+「任務狀態是否 PROCESSING」。退回權(reviewer)是 FE 依專案 participant role 顯示。

4. 狀態機與前置條件

本頁 gate 是任務狀態(不是輪次階段):

TODO ──(PM 於規劃頁「開始執行任務」)──▶ PROCESSING ──(assignee 完成 / 批次完成)──▶ COMPLETED
                                              ▲                        │
                                              └────(reviewer 退回)────┘
條件 效果 出處
預設狀態篩選 = PROCESSING 進頁先看進行中任務(TODO 尚未啟動不顯示) MyTasksView.vue(mount 設 statusFilter)
status === 'PROCESSING' 可上傳 / 留言 / 完成 FE canComplete/canEdit
status === 'COMPLETED' 抽屜唯讀(可看不可改) FE
general 任務就緒 attachment_count > 0(≥1 檔案 / 連結) FE canComplete
survey 任務就緒 所有 task_surveys.status === 9(全完成) FE canComplete

輪次階段與本頁的關係:prep-job 在規劃期(planning)建立、PM「開始執行任務」啟動;受稽方在此執行。任務完成度回饋規劃頁的「證據蒐集執行進度卡」(見 專案規劃頁 §10)。

5. UI 設計

版面骨架與區塊職責(左清單 + 右分割抽屜;body 加 page-fullscreen 讓抽屜獨立捲動;彩色區塊可點跳對應小節錨點,API 僅標代表性):

我的任務頁版面 wireframe:Header 收件匣、左清單面板(搜尋/狀態 pills/專案篩選/批次完成)+ 右 JobExecutionDrawer(描述·證據·連結·留言·完成/退回)

實機截圖(STG,亮色模式,2026-07-05,帳號 blsadmin):

整頁:左清單(我的待辦任務表)

任務明細抽屜:描述 / 任務指南 / 指派人員 / 證據拖放上傳區 / 證據連結 / 評論

批次完成 dialog 截圖從缺:勾選框僅在任務已上傳至少 1 份證據(attachment_count > 0)時才會啟用(見 MyTasksView.vue::canComplete),2026-07-05 盤點 STG 目前所有任務證據數皆為 0,暫無可勾選資料;上傳證據屬寫入動作,不在本次唯讀截圖範圍內。

狀態呈現:任務狀態徽章(TODO/PROCESSING/COMPLETED);可完成任務才可勾選(否則 checkbox disabled 帶原因 tooltip);無 socket,動作後重取清單 / 明細。URL ?job=<uid> / ?execution=<uid> 可深鏈自動開任務(進頁後清 URL)。狀態篩選分段按鈕(TODO/PROCESSING/COMPLETED pills)v1.10.0 起改 outline 視覺(全站 SelectButton 統一調整)。

6. API 規格

Envelope:成功 {"code": 1, "data": …}、失敗 {"code": 0, "msg": "…"}。分頁列表回 PageDataDto(meta + data)。

6.1 總清單(本頁呼叫的全部 endpoint)

分類 Method + Path 說明 完整規格
載入 POST /grc/jobs/my/list 我的任務分頁清單(filters 7 欄,見 §6.2) §6.2
載入 GET /grc/jobs/my/projects/menu 專案篩選下拉 GAI-SD-02
明細 GET /grc/project/{project_uid}/job/{job_uid} 任務明細(指派 / 部門 / 設備 / 問卷 / can_revert_job) §6.3
證據 GET /job-evidences?job_execution_uid={job_uid} 任務證據(FILE / LINK) GAI-SD-02
證據 POST /job-evidences(FILE)・POST /job-evidence(LINK)・PUT/DELETE /job-evidence/{uid} 證據增改刪 GAI-SD-02
留言 GET/POST /grc/job-executions/{job_uid}/comments、PUT/DELETE /grc/job/comment/{uid} 任務留言 GAI-SD-02
檢測 POST /detection-tools/jobs/{job_uid}/execute 開始 / 重新執行掃描(force=true 先中斷再重派;FR-058.7scan_mode=upload 任務可帶 {"source_file":{"uid":"..."}} 指定本次要掃的壓縮包,不帶=沿用綁定現值) §11.1
檢測 POST /file/uploadupload_type='DETECTION_SOURCE' (FR-058.7)上傳源碼壓縮包拿 file uid(既有上傳端點的新分類,非新端點) §11.1
檢測 POST /detection-tools/jobs/{job_uid}/cancel (FR-058)取消執行中的掃描——無 running 執行回 DETECTION_TOOLS_409005、取消失敗回 DETECTION_TOOLS_409004 §11.1
檢測 GET /detection-tools/jobs/{job_uid}/executions 執行歷史(狀態 / 摘要 / 報告清單 / 參數快照) §11.1
檢測 DELETE /detection-tools/executions/{execution_uid} (CM-1425)刪一筆失敗執行紀錄——非 failed 回 DETECTION_TOOLS_409016、查無/跨租戶回 DETECTION_EXECUTION_404001 §11.2
檢測 DELETE /detection-tools/execution-groups/{group_uid} (CM-1425)整組刪(底下全 failed 才准)——混合組回 DETECTION_TOOLS_409017 §11.2
完成 POST /flow-engine/task/complete/{template_job_id} 單任務完成(走 BPMN) GAI-SD-02
退回 POST /flow-engine/task/revert/{template_job_id} 覆核人退回任務 GAI-SD-02
批次 POST /grc/project/{project_uid}/jobs/batch-complete 批次完成(逐專案分送) §6.4
問卷 GET /task-survey/{task_survey_uid}、POST /task-assignees 問卷角色檢查 GAI-SD-02

以下 §6.2~6.4 為核心 endpoint 完整規格(欄位逐條對照 serializer / service 組裝碼,出處標在各段末)。

6.2 我的任務清單

[POST] /grc/jobs/my/list

Request(MyJobListRequestSchema,繼承 RequestMetaSchema):

欄位 型別 必填 說明
pager object {page, page_size, with_total}
sort array 排序條件
filters object MyJobFiltersSchema 共 8 欄皆選填:keyword / status / exclude_status / project_uid / group_keyword / control_code / ao_keyword / round_uid(v1.10.0 新增,CM-846;api/grc/serializers/job.py:192-203;UI 常用前三項+round_uid,其餘供跨群 / 控制項篩選)

Response dataMyJobResponseSchema,每項):

欄位 型別 說明
id string 任務 uid
name / job_type / status string 任務名 / general·survey / TODO·PROCESSING·COMPLETED
project_uid / project_name string 所屬專案
control_group_ / control_ / ao_* string 群組 / 控制項 / AO 定位
workflow_execution_uid string BPMN 執行實體
attachment_count int 證據數(general 就緒判定)
survey_completed bool 問卷全完成(survey 就緒判定)
round_uid / round_no / round_type string / int / string v1.10.0 新增:所屬輪次(vw_user_job_queue LEFT JOIN project_audit_rounds);round_id 為 NULL 的歷史資料 fallback round_no=1round_type='initial'GrcMyJobDto.from_view_row

出處:serializer api/grc/serializers/job.py:205(Request)/ :210(Response);service app/participant/service/task_assignee_service.py:269list_my_grc_jobs:查使用者任務佇列 → 補 attachment_count / survey_completed);DTO app/grc/dto/job_dto.py::GrcMyJobDto.from_view_row

6.3 任務明細

[GET] /grc/project/{project_uid}/job/{job_uid}

Response dataJobDetailResponseSchema):

欄位 型別 說明
id string 任務 uid
name string 任務名
description string 任務描述
guide string 任務指南
job_type string general / survey
status string TODO / PROCESSING / COMPLETED
template_job_id string BPMN 範本 userTask id
can_revert_job bool 是否可退回
workflow_execution_uid string BPMN 執行實體
assignees array 每項 {id, name, avatar, is_approver}
departments array 部門關聯
devices array 設備關聯
surveys array 每項 {id, name, question_count, source_survey_uid, snapshot_uid, approval_required, task_surveys[{task_survey_uid, device_uid, device_name, status, approval_required}]}

出處:api/grc/serializers/job.py:160

6.4 批次完成

[POST] /grc/project/{project_uid}/jobs/batch-complete

Request(BatchCompleteRequestSchema):

欄位 型別 必填 說明
job_uids string[] 要批次完成的任務 uid 陣列
comment string 選填,預設 ""

Response(BatchCompleteResponseSchema):

欄位 型別 說明
total int 送出任務總數
completed_count int 成功完成數
failed_count int 失敗數
results array 每項 {job_uid, success, error}errorNO_EVIDENCE / SURVEY_INCOMPLETE / 任務不存在 / 例外訊息

逐專案分送(FE 依 project 分組多次呼叫);per-job suppress_notify,最後統一批次通知。出處:serializer api/grc/serializers/job_batch_complete.py:5(Request)/ :16(Response);service app/grc/service/job_batch_complete_service.py:30

7. 前端檔案地圖(compliance-manager-fe/)

檔案 角色
src/views/project/MyTasksView.vue 主檢視(左清單 55% + 右抽屜 45%;搜尋 / 篩選 / 批次完成)
src/components/grc/JobExecutionDrawer.vue 任務明細抽屜(證據 / 連結 / 留言 CRUD、完成 / 退回)
src/config/router/index.js:876-880 route project-my-tasks(path /project/task-manage
(留言輸入無獨立元件) 留言 UI 內嵌於 JobExecutionDrawer.vue(約 :151-330),非 CommentInput.vue(該檔不存在)
src/config/api/api.js 端點常數
src/config/locales/i18n/{zh-tw,en}/my-tasks.json 頁面 i18n(namespace lang.my_tasks.*

導覽入口:DashboardView「我的任務」區塊 / 「查看全部」→ router.push({name:'project-my-tasks', query:{job}});問卷開新分頁到 survey-v2-fill。本頁不連 workflow-setup / workflow-view(那是 BPMN 範本編輯,屬另一群)。

8. 後端檔案地圖(本頁核心鏈路)

鏈路 Route App Service 底層
我的任務清單 api/grc/routes/job_route.py:212::MyJobListResource app/participant/service/task_assignee_service.py:269::list_my_grc_jobs(查佇列 + 補 attachment_count / survey_completed) 使用者任務佇列 view(依 task_assignees × job_executions)+ job_evidences count + task_surveys 完成集
任務明細 api/grc/routes/job_route.py:72::ProjectJobDetailResource app/grc/service/job_service.py::get_job job_executions + 關聯表
批次完成 api/grc/routes/job_batch_complete_route.py:19::JobBatchCompleteRoute app/grc/service/job_batch_complete_service.py:30::batch_complete(per-job 就緒複驗 → flow-engine complete → 留言 → 統一通知) infra/grc/repository/job_batch_complete_query.py + workflow service
證據 / 留言 job evidence / comment route job_evidence_service / job_comment_service job_evidences / job_execution_comments

DDD 提醒:清單走 app service(不在 route 查 DB);批次完成的就緒複驗在 service 層、每筆獨立成敗回報(不因一筆失敗整批 rollback)。

9. DB

9.1 資料表總清單(本頁讀寫的全部表)

讀/寫 說明 欄位詳述
compliance.job_executions 讀/(狀態) 任務本體(prep-job):PROCESSING→COMPLETED 見 project-planning §9.3
compliance.task_assignees 任務指派人員(過濾成當前使用者) 見 project-planning §9.3
compliance.job_evidences 任務證據(FILE / LINK) §9.3
compliance.job_execution_comments 任務留言 §9.3
compliance.job_execution_devices / _org_units / _surveys 任務的設備 / 部門 / 問卷關聯(明細顯示) GAI-SD-03
survey.task_surveys 問卷執行狀態(就緒判定 status=9) GAI-SD-03
compliance.projects / project_participants 專案名 / reviewer 角色判定 GAI-SD-03
compliance.detection_executions 讀(本頁)/ 寫(BE 編排服務) 檢測工具執行歷史(狀態/摘要/報告參照),僅 detection_tool 型任務有資料 檢測工具管理 §9
compliance.agent_tasks 讀(間接,反查 agent_task_uid) Agent 派工單(pending/dispatched/running/succeeded/failed/cancelled) 檢測工具管理 §9

清單讀取走「使用者任務佇列」查詢(task_assignees join job_executions 過濾 user_id),批次補 job_evidences 計數與 task_surveys 完成集。v1.10.0:vw_user_job_queue 補 LEFT JOIN compliance.project_audit_rounds(by workflow_execution_control_mapping.round_id),SELECT 加 round_no / round_uid / round_type / round_name 四欄(scripts/sql/2026-07-23-vw-user-job-queue-add-round-info.sql)。

9.3 核心表欄位(取自 DEV DB dump,含 DB comment)

compliance.job_evidences — 任務執行佐證資料

欄位 型別 說明
uid 證據識別
job_execution_id → job_executions(任務本體)
evidence_type FILE(檔案)/ LINK(連結)
reference_url LINK 型 URL
(檔案中繼) 名稱 / 大小 / drive 參照等

compliance.job_execution_comments — 任務執行留言表

欄位 型別 說明
job_execution_id → job_executions
content 留言內容
(作者審計欄) 作者 / 建立時間;作者本人可改刪

job_executions / task_assignees 欄位卡見 專案規劃頁 §9.3(本頁不重複;那裡以寫入者視角、本頁以執行者視角讀寫同組表)。

10. 頁面邏輯與資料對應

載入時序

頁面載入時序:mount 取 URL 參數 → 並行 my/list + projects/menu → 自動開 pending 任務

關鍵欄位對應(畫面 ↔ API):

畫面元素 FE state API 欄位
任務狀態徽章 job.status my/list status
可完成(勾選) canComplete(job) general: attachment_count>0;survey: task_surveys 全 status=9
證據清單 抽屜 evidence /job-evidences
完成按鈕 canCompleteJob flow-engine complete {workflow_execution_uid, comment}
批次結果 兩步 dialog batch-complete results[{job_uid, success, error}]

儲存流程:證據上傳 / 留言後重取明細;完成 / 退回走 flow-engine(BPMN 前進);批次完成逐專案分送、per-job 成敗獨立、最後統一通知。

錯誤對應:BE error envelope → toast;GRC_JOB_NOT_FOUND(404)、GRC_PROJECT_PARTICIPANT_NOT_FOUND(404);批次錯誤碼 NO_EVIDENCE / SURVEY_INCOMPLETE(在 results[].error,非 GRC 碼,FE 對 i18n 顯示)。

11. 背景行為與外部依賴

類型 內容
通知 批次完成 per-job suppress_notify、最後送一則批次摘要通知(threading);檢測工具掃描完成與失敗另發獨立通知(九項內容+報告檔名,Email/Discord/Telegram 三管道,FR-058.7 D34,見 §11.1)
BPMN 完成 / 退回走 flow-engine/task/complete|revert(BPMN userTask 前進 / 回退);prep-job 的 workflow_execution 由規劃期綁定
問卷 survey 型任務開 survey-v2-fill(新分頁);task_surveys.status 追蹤(9=完成)
檢測工具(FR-056) detection_tool 型任務不走 flow-engine complete 觸發掃描——見下方獨立小節
Socket 本頁 socket / 輪詢;動作後重取
jedi-* 套件 jedi-flow-engine(complete / revert)、jedi-survey(問卷)、jedi-auth(JWT)
系統參數 無 feature flag

11.1 檢測工具執行(FR-056,job_type='detection_tool'

任務類型設為「檢測工具執行」(見 任務配置)的 AO 任務,在本頁抽屜顯示「開始執行 / 重新執行」按鈕與「執行紀錄」區塊,走獨立於 flow-engine complete 的編排鏈路

開始執行 / 重新執行JobExecutionDrawer.vue::startExecution()):

  • 無執行中紀錄:直接呼叫 POST /detection-tools/jobs/{job_uid}/execute(無 force),BE 建立 agent_tasks(pending)+ detection_executions(running)派工給具 detection_scan capability 的 Agent,不彈確認框。
  • 有執行中紀錄:先彈確認框(「上一次掃描將被中斷,確定重新執行?」)→ 確認後帶 force: true 呼叫同一 endpoint → BE 先透過既有 FR-039 mTLS 通道直推 Agent POST /detection/cancel 真正中斷上一次掃描(OpenVAS stop_task)→ 確認取消成功才標記舊執行 cancelled 並派新工單;取消失敗(Agent 離線等)→ 回 DETECTION_TOOLS_409004不默默派新的
  • 未帶 force 但已有執行中紀錄 → BE 回 DETECTION_TOOLS_409003(409),防止繞過 FE 直打 API 疊出並行掃描。

SonarQube 上傳模式的執行時上傳(FR-058.7,scan_mode=upload(⚠️ 單槽形狀,FR-067.8 起已改逐列,見本段末「逐列檔案槽」):任務設定選了「上傳原始碼壓縮包」模式的檢測任務(模式選擇見任務配置 §5),抽屜執行區多一塊源碼壓縮包上傳區——壓縮包是「這一次要掃的源碼快照」,故在發起執行時提供而非任務設定表單(D26):

  • 格式與限額:收 .zip.tar.tar.gz.tgz 四格式(裸 .gz 不收——解開只有一個檔,對源碼掃描無意義),上傳上限預設 100MBDETECTION_UPLOAD_MAX_MB 環境變數可調;另有解壓後總量 500MB/檔案數上限等 agent 端防線,D27/D28/D30)。FE 先驗副檔名(source_file_format_invalid toast),走既有 POST /file/uploadupload_type='DETECTION_SOURCE')存進 tenant 儲存空間拿 uid。
  • 首次執行必須上傳:綁定無 sticky 檔案且本次未上傳 → 「開始執行」按鈕 disabled+tooltip 提示(FE 前置擋門);繞過直打 API 由 BE 保底回 DETECTION_TOOLS_400005DETECTION_TOOL_SOURCE_FILE_REQUIRED)。
  • 重掃沿用(D29):已上傳過的任務,上傳區顯示「目前檔案:xxx.zip」——不上傳新檔直接按執行=沿用同一包(execute 不帶 body);要掃新版按「更換檔案」上傳新檔替換(execute body 帶 {"source_file":{"uid":"..."}},覆寫綁定的 sticky 參照)。替換不刪舊檔、歷史版本全保留,每筆執行紀錄的 scan_params 快照都能對回當時實際掃描的檔案(稽核回溯)。
  • FE 只送 uid,不送檔名(D31):BE 收到 execute 後從 upload_files 表權威取回 file_name/size/sha256 寫進快照與派工 payload;uid 查無或不屬本租戶 → DETECTION_TOOLS_404003、格式不符 → 400006、超限 → 400007。執行紀錄與 info 視窗顯示 source_file檔名而非裸 UUID(_PRIMARY_PARAM_KEYSsource_file)。
  • Agent 取檔走 mTLS 主動下載(D25):檔案參照隨心跳 payload 下發,agent 磁碟檢查(不足即報「agent 磁碟空間不足」,歸類環境問題非掃描失敗,D28)→ GET /api/1.0/agents/files/{uid}(純 mTLS、驗證該 uid 屬該 agent 名下 pending/running 任務,否則 DETECTION_TOOLS_404004)→ sha256 對帳 → 安全解壓進 workspace → 接進既有 scan 掃描管線;agent workspace 掃完即刪(tenant 儲存空間上的壓縮包保留)。
  • 上傳無進度條(known limitation):檔案較大時維持轉圈等待至完成。

出處:FE JobExecutionDrawer.vue:296-380(上傳與 sticky 判定)/:741-750(execute 只送新 uid);BE route api/detection_tools/routes/detection_tool_route.py:176-196、util common/util/detection_source_file.py、agent 下載端點 api/remote_agent/routes/remote_agent_route.py::AgentFileDownloadRoute;error code common/code/detection_tools_error_code.py400005400007404003404004);限額 config/config.py:171-172

逐列檔案槽(FR-067.8,2026-08-25):任務設定改「每列自足」之後,scan_mode每個 Agent 分派列各自的參數——同一任務可以一列 pull、兩列 upload,而兩個 upload 列掃的是 不同的源碼包。上述單槽形狀隨之改為逐列:

  • 上傳區逐 upload 列各一個檔案槽(非 upload 列不出現——混模式下 pull 列本來就沒有源碼包 這個概念);多列時標出是哪一列(agent 名),單列時不多這個標籤。
  • 各列各自 sticky:優先讀綁定回來的該列 source_file(BE 從該列參數轉出),讀不到才退回 執行紀錄快照(存量單槽任務的相容路徑)。sticky 只存 uid(metadata 每次派工現查,不留可能 過期的副本),故常拿不到檔名 → 顯示「已上傳(沿用上次)」而非一串裸 UUID。
  • execute payload 改送 source_files{assignment_uid: {uid}}),只帶「這次剛換過檔」 的列——沒送的列代表沿用該列既有的包。無分派列的 fallback 仍同時帶舊的單槽 source_file 欄位(BE 兩邊都收,_default 為路徑保留字)。
  • 擋門逐列且擋在建 group 之前(零工單零執行紀錄,與多 agent 展開的逐台驗證同一立場): 任一 upload 列缺檔就不給按執行,tooltip/BE 訊息都指出是哪一列(agent 名)——只說 「請先上傳源碼包」的話,使用者面對兩三個槽不知道漏了哪個(已上傳的那幾個看起來一切正常)。
  • 單組重跑沿用該列自己的包agent 零改動(憑工單 uid 逐工單下載本就獨立,授權 resolver 讀的是該工單自己的參數)。
  • 自動派發判斷細到列:原本只看任務層參數,會漏掉「任務層 pull、某列 upload」的任務而判成 可自動派——派下去必然打中首次無檔的 400,該錯誤被吞掉只留 warning,且失敗不產生執行紀錄 使冪等條件永遠成立,每按一次「開始執行任務」就再靜默失敗一次

⚠️ 抽屜四處原本讀任務層掃描參數(上傳模式判定、「檢測設定」摘要卡、執行主機清單、掃描 目標清單)在參數搬到列上之後會全部空白且不報錯,看起來像「這個任務沒設定」。已改為讀各 分派列零列時退回任務層走存量相容。 出處:FE JobExecutionDrawer.vue(BE fda3921b/FE a4c5ab4)。

「檢測設定」卡多組時逐組分塊(CM-1396,2026-08-25):初版的跨列彙整(同欄位值不同「/」 併陳、主機清單取聯集)在各組同構時讀得通,SonarQube 混模式(一組「原始碼掃描」、一組 「上傳壓縮包」)直接打穿——「執行模式:上傳原始碼壓縮包/原始碼掃描」下面掛一個 Git 網址, 看不出哪一組是哪個模式、網址是誰的。改法:

  • 多組任務一組一小塊:組號+agent+該組關鍵參數+該組掃描目標清單+該組技術參數摺疊區 (各自開合)。工具名稱與完成模式留卡片頂部(任務級資訊)。單組任務維持原單框版型 (「第 1 組」對單組是純噪音)。
  • 逐組參數過 condition(與任務設定頁擋門、BE 逐列驗證同一套規則)——upload 組上可能躺著 切換模式前殘留的 Git 網址,照列會讓執行者以為那組也要掃該 repo。逐組呈現後不再跨組取 聯集(聯集正是「看不出誰是誰」的來源)。
  • 上傳槽與擋門訊息改標「第 N 組(辨識參數)」(兩處共用同一支函式):agent 名不是穩定 識別(同 agent 可多組、自動挑機的組沒名字)。括號放該組模式+模式專屬識別欄位(Git 網址/ 專案代碼/後綴),刻意不放 profile(基準名太長擠掉真正要區分的);無辨識參數退回 agent 名,再無只留組號。🔴 組號用全部分派列的全域序號(非 upload 列內部序號), 上傳槽與檢測設定卡的組號才對得起來。

掃描目標的台數與原始寫法顯示(CM-1395,2026-08-25/26):CM-1383 的 CIDR/range 語法 落地後,顯示端改「原始寫法+BE 真實台數」原則:

  • 台數由 BE 供、FE 不算(不在 FE 複製第二套展開規則):BE scan_target_spec.display_counts_of() 為唯一入口,「一段代表多台」的寫法(CIDR/range)才給台數;CIDR 語意依欄位分流——展開型 算可用主機(/24=254)、透傳型算整段(256,工具實際處理的量);逐台寫法不給值(段數即 台數)。分派列摘要、執行前確認框、任務資訊區、執行紀錄列台數 chip、執行詳情視窗全吃它。
  • 執行紀錄印原始寫法192.168.50.1-5(5 台)一個 Tag,非 5 個 IP 並排;逐台清單留在 詳情 ⓘ):來源是派工當下快照(工單 params _scan_target_spec)——忠於「那一次掃了 什麼」,不回查分派列現在的設定;快照優先、無快照就地算(透傳欄位存的就是原始寫法, 存量舊紀錄不重跑也能正確顯示台數)。
  • 列上講真正被掃的欄位:執行紀錄回應補 targets(原只挑 hosts);有 targets 就講它 ——nmap 的 hosts 是 agent SSH 登入去執行 nmap 的跳板機,只講它會讓使用者以為網段沒 帶到。判準看資料不看工具清單(「有 targets」=該工具把執行主機與掃描目標分兩欄), 單欄位工具顯示完全不變。台數 chip 與列文字同欄位同 param_schema 短名。
  • FE 過期防護:分派列摘要以 BE 回的 scan_target_spec 字串與畫面現值比對,改了目標未 存檔時退回段數顯示(不顯示過期台數)。
  • 順手:執行詳情長 label(用法寫進標題撐爆兩欄 grid)改 paramShortLabel 短標籤+括號段掛 ⓘ tooltip;未掃到/無實質檢查警示字改 theme-aware token(--color-orange--color-red, 抽 .exec-warn-text.exec-error-text),亮色主題白底可讀(原 --yellow-400 淡黃不可讀)。

取消執行中的掃描(FR-058,POST /detection-tools/jobs/{job_uid}/cancel:執行紀錄中 status='running' 的那筆才顯示「取消執行」按鈕(另需 canEdit)→ 確認框 → BE 走與 force 重派同一條底層 _cancel_running_execution(CM-931 既有):反查 agent_task_uidagent_id → agent base_url,經 mTLS 直推 Agent 取消,成功才agent_tasksdetection_executions 標記為 cancelled。兩種 409:無 running 執行(已結束/從未開始)→ DETECTION_TOOLS_409005DETECTION_TOOL_NO_RUNNING_EXECUTION);取消失敗(Agent 離線、查無 agent_task 等)→ DETECTION_TOOLS_409004DETECTION_TOOL_CANCEL_FAILED),不標記 cancelled(狀態必須反映真實情況,不能讓使用者以為停了其實還在跑)。守門與其他 job 操作端點一致:assert_project_participant(非該專案參與者不可操作)。出處:app/detection_tools/service/detection_orchestration_service.py::cancel_execution:133-155_cancel_running_execution:157-181;FE JobExecutionDrawer.vue::cancelExecution:611-633

按鈕視覺刻意壓小:取消鈕比同列其他按鈕再小一級(text-xs px-2 py-1)並置於 info icon 之後。取消是破壞性、且僅在執行中短暫出現的動作,若與長駐的「下載報告」等重,會把視線拉去一個多數情況下不該按的按鈕。

執行歷史區塊GET /detection-tools/jobs/{job_uid}/executions):新到舊排序(BE ORDER BY started_at DESC, id DESC,CM-930);區塊可收合,有 running 或最新一筆 failed 時預設展開;每筆狀態 running/succeeded/failed/cancelled(Tag 顏色 success/danger/secondary/warning);成功筆顯示「發現 {count} 項」(讀 summary.findings)+「下載報告」。列上只放關鍵資訊(工具名 / profile / 時間 / 觸發者 / 機器數 / 失敗台數 / content 不符警示),完整參數與報告清單走 info 視窗。

執行紀錄群組化(FR-067,2026-08-25):任務設了多組 Agent 分派後(設定端見任務配置 §5「Agent 分派區塊」),一次執行展開為一個執行群組(group)+N 筆執行紀錄(每組 agent+目標各一筆)。API response 改兩層形狀——外層群組(uidstatustotal_countclosed_atis_legacy)、內層 executions[](每筆帶 agent_uidagent_nameassignment_uidscan_targetsis_latest):

  • 群組卡片:彙總徽章 succeeded 綠/partial_failed 黃(部分台失敗,沿 CM-952 語彙)/failed 紅/running 動畫;明細含 scheduled 筆(排程等待中)時顯示「⏱ 排程中」中性徽章與 running 的動態感區隔。卡片內每台一列:agent 名稱/掃描目標/狀態/報告連結。
  • 單組重跑POST /detection-tools/execution-groups/{g}/assignments/{a}/rerun):前置只看該組自己最新一筆是否 failed/cancelled(否則 DETECTION_TOOLS_409013,語意涵蓋 succeeded 與仍在跑)——群組整體還在 running 也可重跑失敗組(CM-1397 放寬:原「群組非 running 才可重跑」讓 30 秒就失敗的組乾等同群組掃一小時的慢組;409012 自此無 raiser,碼位保留不回收,FE i18n 不刪)。同 group 追加新筆;群組已收口才撥回 running 清 closed_at(仍 running 就只追加,不多餘 reopen);收口併發靠 lock_for_close 列鎖序列化,不會出現「一筆 running 掛在 closed 群組下」。重跑一律立即不套排程。重跑歷史(is_latest: false)收合顯示。FE 重跑鈕條件同步放寬(原多擋一層「群組有任一組 active 就不出鈕」已拿掉)。
  • 單組取消.../assignments/{a}/cancel):排程中的組走短路(工單還沒被領走,直接標 cancelled 不打 agent)。
  • 整組取消POST /detection-tools/execution-groups/{g}/cancel):best-effort——可達的台都取消、不可達的記入 failed 清單,全部不可達才 409(409014)。⚠️ FE 讀回應內容呈現結果,不是只看 HTTP 200——failed 清單裡那幾台的掃描還在對方機器上跑。既有 job 層取消端點(上方 FR-058 段)已改委派整組取消,多台情境不會只取消第一筆。
  • 立即開始.../assignments/{a}/start-now):催跑排程中的組(非排程中 409015)。
  • 排程組的執行確認框(FR-067.7):按「開始執行」前若有任何排程組(分派列設了 scheduled_at,設定端見任務配置 §5),確認框列清單——每組一行「agent(目標,含台數,CM-1395)+ 立即/⏱ 時間開始」;時間已過顯示「立即」不顯示過期時間。資料源是綁定讀回的 agent_assignments,不另打 API。排程等待期間群組是 running(守門窗變長)——不能再按執行,要重來先取消整組。
  • legacy 舊資料(group 化之前的筆,group_uid NULL 不 backfill):is_legacy: true 單筆自成一組,形狀與真群組完全一致,FE 不分叉渲染。
  • auto 完成模式:群組全部成功才自動完成任務;partial_failed 不自動完成,留人工判斷。
  • 彙總通知:群組收口時發一封(每台一列:agent/目標/狀態/發現數/時間;發現數空值顯示「—」非 0),取代每筆一封;三通道(Email/Telegram/Discord)同步。失敗原因自 agent 0.2.29 起帶 stderr 尾段(原本 command not found/content 檔不存在這類原因被排空丟棄,UI 只見「執行失敗(exit=1):」空白)。
  • fallback 自動分派(無分派列)仍建群組(total_count=1assignment_uid NULL,路徑用保留字 _default),收口邏輯只有一套。

profile 值的顯示名對照(FR-059):param_schema 宣告 options_source: "profile_library" 的欄位(CINC Auditor / GCB 的 profile),選項已改由掃描設定檔庫動態餵、schema 內不再有靜態 options 可查 label,且值可能是 profile:<uid> 庫內參照。抽屜取 param_schema 後只在真的有宣告時另打一次 profile menu API(fetchProfileLibraryLabels,帶工具 uid)建「值→設定檔名稱」對照,摘要卡與執行詳情因此顯示「TWGCB-01-007 Windows Server 2016 v1.3」而非 profile:<uuid> 裸值;對照拿不到(API 失敗或該參照已停用不在 menu 內)退回顯示原值,不擋畫面也不擋執行。無宣告的工具一次多餘請求都不發。出處:JobExecutionDrawer.vue::fetchProfileLibraryLabels:273-289、值對照 :416。庫的維護與 profile:<uid> 參照機制見 掃描設定檔管理

執行主機與掃描目標分開顯示(FR-058):任務資訊的「檢測設定」摘要卡與執行詳情 info 視窗,皆把 hoststargets 各自整理成一區 Tag 清單(其餘參數走鍵值列,並排除這兩個 key 避免重複)。兩者語意不同——OpenSCAP / OpenVAS / CINC Auditor 這類「登進去掃自己」的工具只有 hosts(維持單框,畫面與加此功能前相同);Nmap 則是 Agent 登入 hosts(執行主機)再對 targets(可能是整個網段)送探測封包,兩者是不同機器。區塊標題一律沿用 BE param_schema 的 label(BE 已依工具各自給對),FE 不寫死「掃描目標」;label 常帶括號說明(如「執行主機(Agent 登入並執行 nmap 的機器,逗號分隔)」),取括號前的短詞當標題以免和後綴的「(N 台)」疊成兩層括號;schema 查無定義時(label 退回原 key)才用 i18n fallback,不顯示英文原始 key。出處:JobExecutionDrawer.vue::paramShortLabeltoolHostList/toolTargetList;執行詳情側自 CM-1395 起改走 execTargetField()(原 execHostList/execTargetList 已刪——只回清單、台數由 caller 數長度的第二套讀法,正是 range 被說成 1 台的來源)。

報告下載(reports,FR-057/CM-952 擴充多檔)DetectionExecutionResponseapi/detection_tools/serializers/detection_tool.py)除舊有單值 report_file_uid 外,新增:

欄位 型別 說明
reports array 該次執行產生的所有報告,每項 {uid, file_name}。真相來源是 job_evidences(handler 逐檔寫入,四台掃描=四筆),非 detection_executions.report_file_id(單值 soft-ref,只留得住第一筆代表);歸屬靠 job_evidences.description[檢測工具] {agent_task_uid} 前綴反解(EVIDENCE_DESC_PREFIX 常數)
report_file_uid string|null 舊語意保留(單值,供舊讀取端相容);FE 已改讀 reports,不再依賴此欄位
detection_tool_name string|null 該次執行的工具顯示名——忠於當筆的 detection_tool_id(任務綁定可能換過工具,歷史列不可一律套當前綁定名稱)
scan_params object|null 當次實際派工的參數快照(agent_tasks.params 反查),已剝除 _credentials 等底線開頭內部欄位——憑證明文絕不可出 API;重掃前可能改過參數,快照忠於當次而非任務當前綁定值
created_user / created_user_name string|null 發動者(審計欄位規範:login_name 配 nickname 成對回傳)

OpenSCAP 逐台各一份報告語意:一次 OpenSCAP 執行掃 N 台目標主機,reports 陣列即含 N 筆——每筆對應該次執行中的一台目標主機(檔名格式 OpenSCAP掃描報告_<host>_<日期>.html),FE 執行紀錄列的「下載報告」改為開清單視窗逐份下載(原本綁單值 report_file_uid 的下載鈕只能拿到第一筆,四台只下載得到一份)。OpenVAS 單台單份的既有行為不受影響(reports 陣列僅一筆)。

完成模式分岔:掃描成功後 BE 依該任務綁定的 completion_modemanual/auto,見 任務配置)決定是否自動呼叫 flow-engine complete;manual(預設)任務維持 PROCESSING,需使用者確認報告後在本頁抽屜手動按「完成任務」(走既有 UC-MT-01 路徑)。

掃描結果通知(FR-058.7 D34 加厚;原 FR-056 僅成功一句話 Email):掃描結束時(on_scan_succeededon_scan_failed 皆會)發通知,失敗也通知——失敗更需要管理層知道,收件人與成功相同:該任務指派人 ∪ 所屬專案 manager/reviewer(以 email 收斂去重;專案反查升級走輪次鏈,legacy 任務 fallback task_assignees.project_id)。內容為九項明細列+條件列:狀態(成功/失敗)、專案、控制項群組、控制項(代碼+名稱)、AO(title→prose→part_id fallback)、任務名稱、工具名稱、目標主機(hosts 獨立一列,照實顯示不遮蔽)、掃描設定(複用執行紀錄同一份剝除——_ 前綴內部欄位+secret envelope 整 key 不出現;profile:<uid> 庫內參照轉譯成設定檔名稱)、開始/結束時間;有報告時另列報告檔名(多檔頓號串接),失敗時另列錯誤訊息。三管道:Email(HTML 表格)+ Discord/Telegram(純文字,依租戶通知設定啟用與否),兩版共用同一份明細列順序不漂移;發送走 thread 不阻塞掃描回報。已知限制:無站內鈴鐺通知(平台無 notifications 表,另案);通知在 agent request context 發、語系一律 zh_Hant_TW(既有限制)。出處:detection_orchestration_service.py::_notify_scan_result:651-_build_notify_rows:733-_dispatch_notification:703-;收件人與 8 層 join 查詢 infra/detection_tools/repository/detection_job_notify_query.py::get_notify_context

scan_params 快照已剝除任務層加密參數(FR-058.0):ZAP 登入後掃描的 login_passwordsecret: true 參數,在 DB 以加密 envelope 存放;scan_params 快照除了既有的「剝除 _credentials 等底線開頭內部欄位」外,加密 envelope 欄位也整個 key 不出現。因此 info 視窗的參數列不會、也不可能顯示任何密碼。詳見 任務配置 §5

出處:BE app/detection_tools/service/detection_orchestration_service.py::start_execution / cancel_execution / list_executions / _resolve_reports;error code common/code/detection_tools_error_code.pyDETECTION_TOOLS_409003 已有執行中 / 409004 取消失敗 / 409005 無可取消的執行);FE JobExecutionDrawer.vueexecReports()reportsArray.isArray 為空才 fallback 單值 report_file_uid)。完整 API / DB 見 檢測工具管理任務配置(規劃頁「開始執行任務」自動派首掃)。

11.2 執行紀錄刪除與逾時收斂(CM-1425)

刪除失敗的執行紀錄

在此之前執行紀錄無法從 UI 刪除,整測與實務上的失敗紀錄(agent 缺工具、連線失敗、設定錯)只會一直累積,只能請原廠下 SQL 清。

狀態 可否刪除 理由
failed 清理對象
succeeded DETECTION_TOOLS_409016 掛著 report_file_id / evidence_id,刪了證據鏈就斷(稽核時找不到當初的報告)
running / scheduled ❌ 同上 東西還在跑,要刪得先按「取消」(取消功能既有)
cancelled ❌ 同上 使用者自己按的,屬有意義的操作軌跡,不是垃圾
端點 前置 行為
DELETE /detection-tools/executions/{execution_uid} 該筆為 failed 硬刪該筆;群組列不動、彙總狀態不重算
DELETE /detection-tools/execution-groups/{group_uid} 群組底下每一筆failed 刪順序 executions → group

三個刻意的設計決定

  1. 刪單筆不重算群組彙總狀態——刪掉一筆失敗紀錄不代表這次執行變成功了。若重算,「四台掛三台」刪掉一台後會變成 partial_failed,等於把歷史事實改寫掉。要讓整組消失請走整組刪。
  2. 整組刪看「每一筆」而非「每 assignment 最新一筆」——收合起來的重跑歷史裡若夾著一筆 succeeded,代表這組留有報告與證據,不該整組消失。
  3. 刪除順序 executions → group(兩表無 DB FK,順序由程式保證)——反過來刪會在中途失敗時留下沒有群組的孤兒 execution,列表會把它們渲染成 legacy 單筆卡。

權限:與同頁其他寫入操作(重跑/取消/立即開始)同一軸——專案參與者(assert_project_participant)+ route 層 @require_license("plugin")。非參與者回 GRC_403053。查無與跨租戶一律 404 不區分DETECTION_EXECUTION_404001),避免成為租戶探測管道。

稽核:刪除寫 system_logs——6120(單筆)/6121(整組),帶操作者、uid 與當時狀態。「刪掉一筆掃描發生過的證據」本身就是稽核關切點。

逾時收斂

問題場景:掃描進行中網路整段不可達、agent 再也沒回報 → 該筆永遠掛 running刪不掉(只准刪 failed)、狀態誤導人,且整組卡 running 會擋掉同一任務的下一次執行。

項目
觸發 背景排程,每 15 分鐘一輪
判定 runningscheduled 超過 DETECTION_EXECUTION_TIMEOUT_HOURS 且 agent 從未回報
閾值 預設 4 小時(環境變數可調;設 0 或負數=停用收斂)
單輪上限 DETECTION_EXECUTION_TIMEOUT_BATCH(預設 200 筆,存量一次撈爆的保險;剩下的下一輪接著處理)
結果 failederror_message 註明「逾時無回報」,並走既有收口路徑重算 group 狀態(與收斂共用同一支,不是兩份真相)

為什麼閾值訂 4 小時:這類掃描本來就慢——逐台登入型工具單台預設逾時就是 1 小時,一次派 256 台是十幾個小時的量級,OpenVAS 全掃數小時也正常。訂太短會把還在正常跑的長掃描誤殺,那比留著卡住更糟:使用者會以為掃壞了而重跑,但實際掃描還在對方機器上跑。

為什麼選背景排程而非「開列表時 lazy 收斂」:lazy 版只在有人打開那個任務的抽屜時才會收斂,但卡住的掃描恰恰是最沒人盯的那些;且整組卡在 running 會擋掉下一次執行,使用者按執行被擋卻不知道要先去開一次抽屜看一眼。排程版跟有沒有人看無關。

兩個功能是串起來的:逾時收斂把卡住的執行判成 failed 之後,它才能被上面的刪除功能刪掉。

12. 邊界情況與已知坑

  1. 本頁 gate 是任務狀態不是輪次階段:TODO 未啟動不顯示;PROCESSING 才可執行;跨專案彙整,非單輪次頁
  2. 就緒條件按任務類型:general 需 ≥1 證據;survey 需全 task_surveys status=9;不就緒 checkbox disabled 帶原因
  3. 批次完成逐專案分送、per-job 獨立成敗:一筆失敗(NO_EVIDENCE / SURVEY_INCOMPLETE)不影響其他;結果摘要逐筆回報,非整批 rollback
  4. 全選只選當前分頁的可完成任務:不跨頁全選(防誤選未見任務)
  5. 退回權是 reviewer(FE 判定)isReviewer 由專案 participant role=reviewer 決定,只在覆核模式顯示退回
  6. 深鏈自動開任務?job= / ?execution= 進頁自動選任務後清 URL(避免連鎖導航)
  7. 證據自成 FILE / LINK 兩型:FILE 走 /job-evidences(multipart)、LINK 走 /job-evidence(FormData json);端點路徑單複數不同,改動注意
  8. 不連 workflow-setup / workflow-view:那是 BPMN 範本編輯頁(另一群),本頁任務執行走抽屜、非全頁導航
  9. 輪次 NULL fallback 語意round_id 未回填的歷史資料(wecm 補欄前產生)fallback 顯示「第 1 輪」+ round_type='initial',對齊 project_audit_rounds 定義的 initial round 語意,非真的查詢該筆屬於第幾輪(v1.10.0,CM-846)

13. 開發與驗證

  • 跑起來:BE python main_socketio.py(port 8000,log 在 log/app.log);FE 在 compliance-manager-fe/ 起 Vite dev server。BE 改 service code 後必須重啟(無 hot reload)
  • 測試帳號:dev 環境被指派任務的受稽方帳號(密碼見 .env / 部署文件)
  • 導航路徑:登入 → 儀表板「我的任務」或直接 /project/task-manage
  • 前置資料:需有專案在規劃頁指派任務給該帳號且 PM 已「開始執行任務」(任務 PROCESSING)
  • E2Ecompliance-manager-test/ repo(Cucumber + Playwright);以 我的任務 / my-tasks 搜尋
  • 相關文件:任務來源見 專案規劃頁;稽核員視角的清單見 我的稽核;DB / API 全量見 GAI-SD-02/03