跳轉到

證據管理 功能群總覽

本檔放「本功能群多個頁面共用的知識」:頁面地圖、AI 證據分類生命週期、兩種「證據」概念的區分、儲存後端與雲端 / Agent 來源、角色基調、核心資料模型。

各頁面 spec 引用本檔,只寫自己頁面的差異——改共用邏輯時改這裡一份。

1. 頁面地圖

本功能群橫跨證據分類閉環(AI 分類 → 覆核 → 報表)與證據來源基礎建設(雲端整合 / 檔案 Agent / 儲存設定)兩塊。

頁面 FE route 用途一句話 spec
自動分類批次清單 /project/projects/:id/round/:roundUid/auto-classify 該輪歷次自動分類作業的歷史清單(入口、續作、清理暫存檔) ✅ 證據分類覆核 §14
自動分類批次流程頁 /project/projects/:id/round/:roundUid/auto-classify/:batchUid 一批作業的四步流程:上傳 → AI 分類 → 確認分類 → 歸檔完成 ✅ 證據分類覆核 §14
證據分類覆核(批次線) /project/projects/:id/evidence-batches/:batchUid/review/:runUid 分類結果逐檔審閱 + 手動修正(嵌在批次流程頁第③步) ✅ 證據分類覆核
證據分類覆核(Drive 線) /project/projects/:id/ap/:apUid/classify-evidence/run/:runFolderId 同上,舊 Drive 分類結果的入口 ✅ 證據分類覆核
分類驗證報表 .../run/:runFolderId/report/validation 對照 User 修正後狀態,量化 AI 準度(召回 / 精確) ✅ 分類驗證報表
分類誤判報表 .../run/:runFolderId/report/adjudication 以中立正解基準(CANON)裁判 AI vs User ✅ 分類誤判報表
雲端整合(Drive) /settings/cloud-integrations 租戶 Google Drive 連接 / 同步狀態管理 ✅ 雲端整合
檔案 Agent 管理 /system/remote-agent-manage FR-039 客戶端檔案 Agent 端點登錄 / 狀態 ✅ 檔案 Agent 管理
儲存設定 /system/storage-config 全租戶檔案儲存後端(local / MinIO / remote_agent / Drive)設定 ✅ 儲存設定

兩份分類報表(validation / adjudication)是同一個 run 的下游唯讀檢視,各自對應獨立 FE route 與 view,分為兩份 spec:驗證報表(量化準確度)與誤判報表(質化誰對誰錯)。

2. AI 證據分類生命週期(本群分類閉環的核心)

分類有兩條線並存,差別在「檔案從哪來、分完去哪」:

批次線(現行主線) Drive 線(既有資料)
檔案來源 使用者上傳進暫存批次,落在租戶自己的儲存後端(本機/MinIO/SeaweedFS/遠端 agent 皆可) Google Drive 的 Evidences/ 資料夾
掛在誰身上 稽核輪次(round_id),每次新上傳開一個新批次 專案的 AP
分完之後 歸檔進任務——檔案改綁對應的控制任務,在 job_evidences 真正寫入一筆,任務證據頁看得到 把檔案複製進 Drive 的 per-AO 資料夾,系統的任務證據表不寫入
前置要求 租戶已設定檔案儲存位置(未設定時整頁擋下並提示去系統設定) 租戶 Drive CONNECTED + AP 已 init 資料夾 + Evidences 有檔案
定址 run_uid(UUID),目標集吃 run 的 catalog_snapshot run_folder_id(Drive 資料夾 ID)

落地版客戶沒有 Google Drive,批次線是讓分類功能對他們也能用的前提。Drive 線不再是新功能的落點,保留是為了讓既有分類結果仍打得開。

2.1 批次線的四步與狀態

畫面是四步流程(AutoClassifyBatch.vue):① 上傳證據 → ② AI 分類中 → ③ 確認分類 → ④ 歸檔完成;第③步嵌入的就是證據分類覆核頁。

批次狀態(compliance.evidence_batches.status):uploading → ready(按「完成上傳」)→ classifying(按「開始 AI 分類」)→ review(容器跑完)→ archived(按「歸檔進任務」);分類失敗落 failed,已上傳的檔都還在、重新分類不必重傳。

轉換規則的唯一真相是套件的 ALLOWED_TRANSITIONS(動作 → {來源狀態: 目標狀態}),查不到即非法轉換回 EC_409002。幾個不直觀但刻意的設計:

  • ready 再加檔會退回 uploading(要重按一次「完成上傳」)——批次的檔案清單是分類的輸入,加了檔就不再是先前那份。
  • review 可以再跑一次分類(換模型或門檻重判),也可以在審閱時剔掉不要的檔。
  • archived → archived 放行(重按歸檔冪等):擋掉第二次的話,「歸檔後才建出來的任務」永遠拿不到證據,而使用者看到的是一個無法補救的錯誤。已歸檔批次的按鈕字樣降級為「重新歸檔」,只補上次歸檔後才新建的任務。
  • 分類進行中封口(加檔/刪檔被擋回 EC_409003,前端顯示「分類進行中不能改檔」而不是泛用的狀態錯誤)。
  • 心跳:執行緒每 60 秒蓋一次 job_heartbeat_at,BE 啟動時掃出逾時 30 分鐘的判失敗(failure_reason = heartbeat_timeout,前端據此顯示「可直接重跑」)。這是判「執行緒還活著嗎」不是「跑完了沒」,超大批次真跑三小時也會一路蓋心跳。

按「開始 AI 分類」前會先開一個設定視窗,三個欄位:

欄位 說明
信心門檻 低於這個信心的判斷留給人工確認(滑桿,0.50~1.00)
AI 模型 僅系統管理員可見(一般使用者不該也不需要挑模型)。平鋪一層列出可用型號,清單是動態算的——只列已設金鑰的供應商,沒設金鑰的家不出現也不提示。一把金鑰都沒設時下拉是空的、「開始分類」反灰並提示去系統設定填金鑰
思考深度 低/中/高三檔,預設中——控制模型花多少力氣推理。沒指定時的解析順序是「這一批指定的 → 分類設定的預設 → 系統預設(中)」

送出時型號與供應商要一起送:後端沒收到供應商會從碼表反查,反查不到才退預設那家——兩者都落空時選到的型號會被判成「不支援的分類模型」。

視窗上另有三個預估數字(耗時/用量/費用),用意是在「按下去之前」提供決策依據。

歸檔取的是審閱後的判定(run 的 state),且標了「不適用」或已刪除的檔一律不掛——審閱頁標這兩個旗標時不會一併清掉 placements,只看 placements 的話使用者標了「不適用」的檔還是會被掛上任務。歸檔回傳四個數字:掛進任務的檔數、新產生的證據筆數、原本就在任務底下所以略過的筆數、沒有對應任務的檔數。

清理(purge)只對已歸檔的批次開放,且已歸檔的檔永遠不在清理範圍內——那些檔背後有 job_evidences 指著同一個檔案 id,實刪後任務上的證據會變成打不開的死連結。

2.2 Drive 線(既有資料)

流程(FR-030):Drive Evidences/ 資料夾 → 觸發分類(manager)→ 容器 AI 逐檔分類 → run 資料夾 + _state.json → 覆核修正 → 報表 → 歸檔。

證據分類生命週期:觸發(manager)→ 容器 AI → run folder(_state.json)→ 覆核 → 驗證/誤判報表 → 歸檔

run 狀態(evidence_classification_runs.status):queued → processing → completed(成功)/ failed(容器 exit≠0);archived_files 旗標另記是否已把 placement 檔複製進 per-AO 資料夾(analyze-only 模式先不複製,覆核後手動歸檔)。

真相來源雙寫:placement 編輯狀態的真相是 Drive 上的 _state.json(覆核頁讀寫的就是它);evidence_classification_runs.state / report_original JSONB 是 DB 鏡像(供報表與跨頁查詢,_sync_run_state_to_db idempotent 同步)。報表以 report_original(AI 首次輸出,immutable)對照 state(User 修正後)計算。

2.3 兩條線共通的概念

分類單位是 per-檢查點 placement——一個檔案可以命中多個檢查點,命中幾個就在那幾個任務底下各掛一筆證據(不複製檔案,多個任務指向同一份檔)。兩條線的檢查點代號寫法不同:

代號形式 目標集(AI 可選的檢查點母體)從哪來
批次線 part_id + ao_letter(如 IA.L1-3.5.1_obj.1) run 的 catalog_snapshot——分類當下凍結的那一份,與這次判定必然對得齊
Drive 線 {ControlId}[{letter}](如 AC.L1-3.1.1[a]) living SSP 的 in-scope 控制集(見 專案規劃頁)

目標集用凍結快照而不是即時查:控制集在分類跑完到使用者審閱之間可能被改動,拿即時的去對照會出現「AI 判到一個現在已經不存在的檢查點」。

哪些 AI 模型可選=該租戶已設定金鑰的供應商 × 系統支援的型號表取交集,由 GET /api/1.0/classification/available-models 動態算出,不寫死在畫面上。沒設定任何金鑰時回空清單並提示去系統設定填,比列出一堆選了才 401 的型號好。型號表是資料不是邏輯(支援新型號=加一列),實際可選清單隨金鑰設定與型號表變動——故本手冊不列型號名,要看當下有哪些請打該端點。金鑰維護見框架版本管理 §1.1。

3. 兩種「證據」概念(新人最易混淆,先分清)

系統中「證據」有兩種獨立但相關的身份,不是同一份資料:

Job Evidence(任務佐證) Classification Evidence(分類證據)
表 / 位置 compliance.job_evidences(綁 job_execution_id) 批次線:compliance.evidence_batch_files(暫存,未歸檔前)/ Drive 線:Evidences/[domain]/[control]/[ao]/ 資料夾內檔案
來源 SYSTEM_UPLOAD(手動)/ DRIVE_SYNC(Drive 同步)/ DETECTION_TOOL(FR-056 檢測工具掃描報告,PDF)/ AI_CLASSIFIED(批次線歸檔寫入,帶 classification_run_id 可追溯) AI 分類放置或 User 手動複製
用途 任務執行的完成佐證(受稽方上傳) AP 合規評估的框架相關檔案
涉及頁面 我的任務 本群分類覆核 / 報表
關聯 批次線歸檔會在此真正寫入一筆(source='AI_CLASSIFIED');Drive 線不寫 批次線歸檔後即成為左欄那筆;Drive 線分完仍留在 Drive

批次線是這兩種身份唯一的接點:歸檔那一步把暫存批次的檔改綁控制任務,於是分類證據變成任務佐證(source='AI_CLASSIFIED' + classification_run_id 記得從哪一次分類來的)。Drive 線沒有這個接點——它分完只是把檔複製進 Drive 的 per-AO 資料夾,job_evidences 一筆都不寫。

除此之外兩者的交集只在「檔案存哪」——都由租戶的 STORAGE_CONFIG 決定儲存後端(見 §4)。改 Drive 線邏輯不要誤動 job_evidences,反之亦然。

4. 儲存後端與證據來源

本群管的是「證據檔案存哪、從哪來」的基礎建設:

面向 頁面 / 機制 說明
儲存後端切換 儲存設定(STORAGE_CONFIG system config,per-tenant) storage_type:local / minio / remote_agent / Drive;重用 jedi-file-upload 的 IUploadFileProvider adapter
雲端來源 雲端整合(tenant_drive_integrations) Google Drive OAuth 連接、webhook 同步、資料夾對應(drive_folder_mappings,scope 含 EVIDENCES)
客戶端落地 檔案 Agent 管理(remote_agents,FR-039) 機敏證據不上雲、落地客戶自有設備;agent 以 device fingerprint 綁定、心跳回報 status

背景同步:Drive 變更經 webhook → drive_sync_jobs 佇列非同步處理(詳見背景服務 spec)。分類前置要求:租戶 Drive CONNECTED + AP 已 init Drive 資料夾 + Evidences 有檔案。

5. 角色權限基調

角色是誰:

  • manager(專案負責人)——觸發這一輪的 AI 證據分類。「身為 manager,我要對這次稽核的證據資料夾觸發 AI 分類,把檔案自動配對到對應控制項。」
  • 稽核參與者(v1 簡化:任何登入者)——覆核 AI 分類結果、修正誤判、查看分類報表。「身為稽核參與者,我要檢查 AI 分類的檔案是否放對控制項,把錯的改回來。」
  • 租戶 admin——設定證據存哪(本地 / MinIO / Drive)、管理雲端整合與客戶端檔案 Agent。「身為租戶 admin,我要設定這個租戶的證據要存在哪裡、要不要接 Google Drive。」

本群橫跨專案層(分類)與系統/租戶層(整合 / Agent / 儲存)兩種權限基礎:

動作 誰能做 檢查
批次的寫入類動作(建批次 / 上傳 / 刪檔 / 開始分類 / 歸檔 / 清理) 專案 manager service 層 is_project_manager(),否則 EC_403005(專用碼:泛用的「僅可觸發自動分類」文案對不上使用者當下在做的事)
看批次清單與流程頁 專案參與者 service 層 is_project_participant(),否則 EC_403002;auditor 進得去但按鈕整組隱藏並顯示一行說明(反灰會讓人一直想「怎樣才能按」)
AI 分類設定(profile)CRUD 租戶管理員(跨租戶由 RLS 擋) service 層;ROOT 出廠那份對業務租戶唯讀,改它回 EC_403004
AI 供應商金鑰 ROOT 平台管理員(第一版不開放客戶自填) 系統設定頁另鎖,讀取時遮成 is_set 旗標、不回明文
觸發 AI 分類(Drive 線) 專案 manager service 層 project_participant.role == "manager",否則 EC_403001
覆核 / 編輯 placement / 存 / 歸檔 v1 簡化:僅 JWT(未檢專案角色,實驗階段) 見 evidence-classification-review §3
檢視報表 同覆核 —
雲端整合 / 儲存設定 / Agent 管理 租戶 admin(系統管理層) 各頁 capability / route 層

本群 error code 前綴是 EC_(evidence_classification 模組),不是 GRC_——命名規則同(EC_<HTTP狀態碼><序號>),檔案在 common/code/evidence_classification_error_code.py。查錯別在 grc_error_code.py 找。

6. 核心資料模型

證據管理核心資料模型:分類 run(藍)鏡像 Drive _state.json + ground truth;Drive 整合 / 資料夾對應 / remote agent 為來源;job_evidences 另一條線

表 schema 角色
evidence_batches compliance 批次線的一批作業(掛 round_id;status 六態、provider / model / confidence_threshold / profile_id 記這批用什麼跑、job_heartbeat_at 心跳、四個計數欄與歸檔/清理的時間與操作者)
evidence_batch_files compliance 批次內的暫存檔(status:pending / classified / no_task / archived / removed;archived 的列不可從批次這側實刪,背後有 job_evidences 指著同一個檔)
classification_profiles compliance AI 分類設定(per 租戶 × 框架版本;persona / guidance / evidence_hints + 供應商與模型預設值;tenant_id=1 是 ROOT 出廠通用設定。軟參照框架版本、刻意不建 FK——那張表屬另一支插件,插件互不相依)
evidence_classification_runs compliance 分類 run 記錄(兩條線共用;state / report_original / catalog_snapshot JSONB。批次線以 run_uid 定址,Drive 線以 run_folder_id 自然鍵並鏡像 Drive run folder)
evidence_classification_ground_truth compliance 正解基準(per-tenant × framework;mapping JSONB = {file_name:[ao_id]};誤判報表 CANON 來源)
tenant_drive_integrations public 租戶 Google Drive OAuth 連接(token / webhook / 同步狀態)
drive_folder_mappings public Drive 資料夾 ↔ 系統實體對應(scope_type 含 PROJECT/AP/EVIDENCES…)
drive_sync_jobs public Drive 同步任務佇列(webhook 驅動、非同步)
remote_agents compliance FR-039 客戶端檔案 Agent registry(device fingerprint / status / 心跳;capabilities 欄位 FR-056 起兼作檢測工具掃描能力清單)
remote_agent_enroll_tokens compliance Agent 綁定 enrollment token(sha256 hash)
job_evidences compliance 任務佐證(另一種證據,見 §3;儲存後端由 STORAGE_CONFIG 決定;source 含 DETECTION_TOOL 與 AI_CLASSIFIED,後者另有 classification_run_id 軟參照回分類 run)
detection_executions compliance FR-056 檢測工具執行歷史(狀態/摘要統計/報告與證據參照,見 任務執行抽屜、檢測工具管理)
agent_tasks compliance FR-056 Agent 派工單(掃描指令 + 加密憑證隨派下發,狀態機 pending→dispatched→running→succeeded/failed/cancelled)

7. 本群共用的已知坑

  1. 兩種「證據」別混:job_evidences(任務佐證)vs 分類證據,是不同資料;批次線歸檔是唯一把後者變成前者的路徑(見 §3)
  2. 真相在哪要看是哪條線:Drive 線的 placement 真相是 Drive 上的 _state.json,DB state 是鏡像,直接改 DB 會與 Drive 脫鉤;批次線沒有 Drive,run 的 state 本身就是真相 2a. 批次線的目標集是凍結快照:審閱頁對照的檢查點來自 run 的 catalog_snapshot,不是即時查控制集。快照缺 part_id 的項目會被歸檔略過(拿它去查任務只會全部落到「無對應任務」);EC_412007 即「此 run 無目標集快照,請重新分類」 2b. 清理永遠不動已歸檔的檔:archived 不在可清理範圍內且不該加進去——那些檔背後有 job_evidences 指著同一個檔案 id,實刪後任務上的證據會變成打不開的死連結
  3. 報表即時計算不存確認狀態:validation / adjudication 每次開都重算(對照 report_original immutable × state current),沒有「已確認」持久欄位
  4. error code 前綴 EC_ 不是 GRC_,且定義在套件裡不在主專案:查錯去套件 jedi_evidence_classification/common/error_code.py(EvidenceClassificationErrorCode),主專案 common/code/ 下沒有這支
  5. 框架知識不再寫死、批次線不需要 Drive:要換框架改的是 classification_profiles 這筆資料(AI 角色 / 指引 / 證據提示),不是改程式碼;四層退路是「租戶×框架版本 → ROOT×框架版本 → 租戶通用 → ROOT 通用」,全落空才用內建最小版(內建那份刻意不含任何框架名——寫死 CMMC 等於把框架名焊回分類引擎)
  6. remote agent demo 邊界:FR-039 demo 階段落地不加密、無認證金鑰、無網路可達性檢查(見 FR-039 design)
  7. 兩條線的覆核權限不同:批次線的寫入類動作鎖專案 manager、看的人要是專案參與者(auditor 唯讀);Drive 線的覆核 / 存 / 歸檔仍僅需 JWT(實驗階段遺留,非資安定案)