FR-143 · 設計定案 · 2026-10-17
左樹只列不符合、稽核缺失文件表單、對原任務逐一設執行人員/改善期限/改善措施、送出即退回第一站重跑、側邊入口表格、Excel 往右延伸一列一任務、OSCAL POA&M 匯出合規
缺失改善頁整個換掉。左樹只列這次判不符合的評估目標;點一條,上半是「稽核缺失」文件表單(稽核發現、風險、稽核建議、稽核人員、查核方法、採用佐證),下半列出這條評估目標底下的原任務,PM 對每個任務設執行人員(可多人)、改善期限、改善措施,不新增任務。只排計畫不追蹤完成,送出就推進:內稽每個任務退回第一站整條重跑、改善期限寫進每一站;外稽進待覆核。側邊選單多一個「改善計畫」表格入口。Excel 與稽核計畫、稽核結果同一份往右延伸,一列一個任務、合併儲存格。資料照 OSCAL POA&M 標準落點,並修 jedi-oscal-v2 四處匯出不合規。本文件寫定案規則、為什麼這樣定、踩到會怎樣。
🔴 這份是設計決策,不是現況。 內文停在 2026-10-17 定稿當時,實作改動不回頭改寫這裡。
狀態:設計定案(2026-10-17)|母卡 CM-2840|子卡 CM-2841~2846|討論稿:
discussion.md|雛形:prototype/index.html|範例 Excel:prototype/sample/FR-143-改善計畫範例.xlsx
檔案路徑與行號以 2026-10-17 為準,查不到時以函式名重新定位。路徑慣例:BE 路徑相對
compliance-manager-be/;pkg/<套件>/代表~/Projects/Jedicogy/module/jedi-python-package/<套件>/<套件底線名>/;FE 路徑相對compliance-manager-fe/。三個 repo 都在feature/FR-139(FR-140、141、142 已併入)。
名詞:評估目標=AO,控制項底下的檢查項目,全系統用 part_id 當鍵(<控制項代碼>_obj.N);POA&M=改善計畫(plan of action and milestones),OSCAL 評估層第三個文件;poam-item=一條缺失的封面,引用 finding;risk=風險;response=風險的處置計畫(表 assessment_remediations,程式稱 remediation),lifecycle:recommendation 稽核建議/planned 改善計畫;task=response 底下一筆(表 poam_milestones),本案一筆 task 對一個系統任務;任務=一條工作流程(compliance.workflow_executions),底下可能多站(job_executions,例如證據上傳 → 主管檢核 → 顧問檢核);稽核次=FR-140 的 audit_round_passes,一輪內每做一次稽核一筆,各自一組 AP/AR/POA&M。
| 日期 | 變更 | 對應 |
|---|---|---|
| 2026-10-17 | v1:D1~D12 定案;資料模型與 OSCAL 落點、API、畫面、Excel 契約、退卡規則、六棒六張卡、端到端驗收 | 母卡 CM-2840 |
| 2026-10-17 | v1.1:修任務粒度自相矛盾——一塊對一條流程(不是一站一塊),執行人員只改第一站;D3、D5、D10、驗收 2 與 5 改寫 | 棒 2、5 驗收時發現,決策者裁 A 案 |
| 2026-10-17 | v1.2:D9 清單改依專案分組展開(與 FR-142 稽核作業同一套),小字「共 N 份改善計畫」;待規劃判準補輪次仍在 remediation | 決策者裁;棒 7 CM-2851 |
整案一句話:缺失改善頁換成左樹只列不符合評估目標、中間上半看稽核缺失、下半對原任務逐一設執行人員/改善期限/改善措施,送出就把任務退回第一站重跑不等改完;側邊選單多一個「改善計畫」表格入口;Excel 與前兩階段同一份往右延伸;POA&M 匯出合規。
| 卡 | 做什麼 | 產出 | 完成怎麼判定(決策者親手做什麼、看到什麼) |
|---|---|---|---|
| 1 | 套件 POA&M 匯出合規與守門改法 | jedi-oscal-v2 匯出修四處;jedi-compliance-audit 守門改「計畫齊全」、task 對應任務 | DEV 一個有不符合的稽核次送出改善計畫後,匯出 OSCAL JSON 用官方 schema 驗證通過,檔內每個 task 有改善期限與執行人員 |
| 2 | BE 改善計畫端點 | 新 app service、route、schema、error code | Swagger 存一條有兩條流程的評估目標讀回一致;有流程沒填齊送出回 412 列出是哪個;送出後再存回 409 |
| 3 | FE 改善計畫頁 | 新頁、子元件、舊頁退役 | 對照雛形畫面 1 逐頁操作,每個動作對應後端真資料 |
| 4 | Excel 匯入匯出 | workbook 讀寫、預覽 | 匯出改兩列匯回,預覽標出、確認後畫面更新;寫一個不是成員的名字預覽要求處理 |
| 5 | 退卡改第一站重跑、改善期限寫每一站 | 新 job_restart_service.py、退卡與覆核輪改接 |
三站流程全完成後送出改善計畫:第一站回進行中、後兩站回待辦、三站改善期限都是計畫日期、第一站指派人=執行人員、後兩站指派人不變 |
| 6 | 側邊選單「改善計畫」入口 | 讀模型、端點、FE 表格頁、路由 seed | PM 帳號登入,側邊選單「改善計畫」看到待規劃稽核次表格、點列進該輪;只當 auditor 的帳號看不到或為空 |
| 7 | 清單改依專案分組展開 | FE 頁改寫、共用分組 composable | 「全部」頁籤同專案只一列、點列展開子列由舊到新、「目前」標在最急那次、全部展開/收合、搜稽核次自動展開;稽核作業頁行為不變 |
依賴:1 先做 →(2、4、5 可平行)→ 3 等 2;6 等 2。
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
flowchart LR
C1[1 套件修正] --> C2[2 BE 端點]
C1 --> C4[4 Excel]
C1 --> C5[5 退卡重跑]
C2 --> C3[3 FE 頁面]
C2 --> C6[6 入口清單]
全部由決策者 2026-10-17 拍板,討論過程見討論稿。
D1 粒度=逐不符合評估目標;控制項只是分組 左樹到評估目標,每條各自規劃;控制項總覽只是彙總。OSCAL poam-item 對 finding(FR-142 起 finding 已是評估目標層)。排除:控制項層一筆(第 2 次內稽縮範圍是評估目標層,對不上)。
D2 只排計畫不追蹤完成 沒有打勾、沒有進度條;改好沒有=下一次稽核判定。poam_milestones.status/completed_at 停用不刪。排除:保留打勾但不當守門(兩套真相)。
D3 不新增任務;對評估目標底下的原任務逐一設執行人員、改善期限、改善措施;守門=每個任務三欄齊;送出後鎖定 「任務」=一條工作流程(workflow_execution_control_mapping 掛的那一層),一條流程底下可能多站(證據上傳 → 主管檢核 → 顧問檢核);畫面一塊對一條流程,不是一站一塊。站只唯讀顯示名稱與狀態。一條評估目標底下有幾條流程就列幾塊,有缺失就都要退回,沒有「納不納入」。每塊:執行人員(可多人,預設第一站原指派人)、改善期限(即里程碑)、改善措施(可一鍵帶入稽核建議)。有任務沒填齊就擋送出並列出「任務名 未填:X」;送出後整份唯讀。排除:一站一塊(檢核站的人是流程範本定的,不該在改善計畫頁換;PM 要填三倍);PM 自建改善任務清單;一個任務多個里程碑;任務可勾不納入;送出後仍可改改善期限。
D4 改善期限逐任務設定、寫回該任務;一個任務對多條評估目標時共用執行人員與改善期限 畫面上同一任務在第二條評估目標出現時顯示「此任務同時對應 X,執行人員與改善期限一併套用」。排除:一條評估目標一個改善期限套全部任務;取最早或最晚。
D5 執行人員=流程第一站的指派人,可多人,預設帶第一站原指派人,PM 可加減;送出時只改寫第一站的 task_assignees,後續站維持原人 DEV 實查三站流程每站各有其人(執行者/主管/顧問);改善計畫的執行人員是「誰去改」,檢核站的人不因排計畫而換。送出確認表註明相較原指派人增減了誰。排除:三站都換成執行人員(執行人員自己檢核自己);計畫上另記負責人、任務指派人不動。
D6 Excel=與稽核計畫、稽核結果同一份往右延伸;一列一個任務;同評估目標的灰底欄合併儲存格 契約見「Excel 契約」。決策者原則「每階段往右加欄,最後是完整軌跡」(FR-142 D9 已定);一格換行 user 一定填錯、往右長一組 user 不會用。排除:一格多值換行;每任務往右長一組;砍計畫欄只留重點;執行人員拆三欄。
D7 匯出兩個:Excel 工作表、OSCAL POA&M JSON;不做 Word/PDF 報告 OSCAL POA&M 頂層沒有文件正文欄位(AP 有 terms-and-conditions,POA&M 只有 metadata/remarks),硬放等於自創欄位;業界 POA&M 交付物就是表格(FedRAMP 官方範本是 Excel)。排除:報告 docx/pdf;概要頁籤;併進稽核報告。
D8 舊資料不管 既有輪次的改善計畫不遷移、不處理。新頁只服務本案上線後結案的稽核次。排除:寫遷移;新頁唯讀顯示舊資料。
D9 側邊選單加「改善計畫」入口(不加「我的」),表格依專案分組展開,列出我是專案經理的輪次 與 FR-142 稽核作業同一套:一專案一列,專案列的值取「目前這一次」(待規劃 > 已送出 > 覆核中 > 已結束,同狀態取最晚期限最近);專案名下小字「共 N 份改善計畫 · 第 R 輪 · 標準」(N=該專案有改善計畫的稽核次數,決策者裁 A 案)。點專案列展開子列:該專案每一份改善計畫依結案日由舊到新,「目前」加粗標 tag;只有一份的不展開、小字直接寫稽核次、點列直接進。預設展開有待規劃的專案;工具列「全部展開/收合」。欄位:狀態、已規劃/不符合、退回任務數、最晚期限(30 天內橘、過期紅)、稽核結案、送出日。狀態頁籤仍算稽核次、預設「待規劃」,篩選後子列只剩符合的並加「(符合篩選 M 次)」;可篩稽核性質與標準、搜專案名與稽核次(命中子列自動展開並標黃)。排序、分頁以專案為單位,每頁 10 個專案。前端一次撈全部稽核次後分組;分組 composable 與稽核作業頁共用(useAuditWorkGroups,注入預設展開規則與專案列額外欄位)。登入者判準只看「是該專案 manager」;待規劃=輪次仍在 remediation 且為目前稽核次且改善計畫未送出。理由:排計畫的人是 PM,入口藏在專案三層內是「不知道怎麼用」的原因之一;同專案多次稽核平列時看不出卡在哪。排除:卡片式;平列一稽核次一列(第一版,決策者改判分組);進度條;小字寫「共 N 次稽核」(B 案,子列只列有改善計畫的那幾次,數字對不上);併進「我的稽核」當分頁。
D10 退卡=每個任務退回第一站整條重跑 現行內稽退卡只把最新那一站改回進行中(not_met_job_redo_service._redo_one 用 pick_latest),三站流程全完成時重開的是顧問檢核,補證據的人改不到;DEV 現有 6 筆退卡紀錄全是單站流程,沒被測出來。定案:第一站改回進行中、通知第一站指派人(=執行人員);後續站改回待辦、保留原指派人,前一站完成才依序往下。改善措施照舊寫成任務上的系統留言。外稽覆核輪產新任務同理從第一站開始。排除:只重開最新站;讓 PM 選退到哪一站。
D11 不設「暫行緩解措施」欄 改好之前先做的臨時防護本來就該寫進該任務的改善措施。OSCAL risk.mitigating-factors 匯出留空。
D12 改善期限寫進該任務的每一站,不加欄位、不動 jedi-flow-engine 期限欄 job_executions.due_at 已存在(FR-140),但只在每一站上,流程主表沒有;complete_job 推出下一站不帶期限。定案:退卡時把 PM 設的改善期限寫進該任務全部站的 due_at(due_at_manual=false)。排除:流程主表加欄(動套件);流程變數;只壓第一站。
oscal)三層既有,不加表:assessment_risks(status、deadline、mitigating_factors)→ assessment_remediations(lifecycle、title、description)→ poam_milestones(task_type、title、description、assignee_user_id、assignee_org_unit_id、target_date、status、completed_at、props)。poams(status)、poam_items(related_findings)。產生:pkg/jedi-oscal-v2/app/service/poam/poam_service.py:54 generate_from_findings,FR-142 結案 finalize_assessment 呼叫,每筆 not_met finding 一個 item(finding 已是評估目標層,粒度自然對)。
pkg/jedi-oscal-v2/app/service/io/oscal_io_service.py,1,697 行超標)_risk_to_json(:1538)、_remediation_to_json(:1564)、_milestone_to_task_json(:1584)、_export_poam(:1600)、_poam_item_to_json(:1685)。四個不合規見「OSCAL 落點」。超標檔只准新開 poam_export_parts.py 再從原檔一行呼叫。
pkg/jedi-compliance-audit/app/service/poam_app_service.py(493 行):list_items、get_item、add_remediation、add_milestone、update_milestone、all_items_closed(:421)、earliest_milestone_dates(:434)、milestones_by_control(:449)。pkg/jedi-compliance-audit/app/service/audit_round_pass_transitions.py:96 _close_on_pass:all_items_closed 不成立拋 GRC_POAM_NOT_ALL_CLOSED(GRC_412005)——這就是「要等改完才能走」的根。pkg/jedi-compliance-audit/app/service/audit_round_app_service.py(918 行超標):finalize_audit(:470)、close_round(:522)、launch_reverify(:543)。api/project/__init__.py:109-114 掛 /audit-round/<round_uid>/poam-items、poam-item/<item_uid>、remediation/<uid>、poam-milestone/<uid>;route 在 api/project/routes/audit_round_route.py:380-485,守門 @require_capability("grc.audit.read")(讀)、grc.audit.create/grc.audit.update(寫)。app/flow_control/service/not_met_job_redo_service.py(126 行)redo_not_met_jobs → _redo_one → app/flow_engine/service/job_reopen.py reopen_job_execution;期限 job_due_date_service.due_at_from_milestone_date(台北 23:59:59)。app/flow_engine/service/workflow_execution_service.py:787 revert_job(目標站重開、後續站改 TODO;帶 assert_job_operator 與輪次凍結守門,系統退卡不可直接呼叫)。common/code/flow_control_error_code.py:100-109、285-286(GRC_POAM_*)。src/views/project/RoundPoamView.vue(890 行超標)掛 /project/projects/:id/round/:roundUid/poam(router index.js:1130);端點常數 api.js:296-298;i18n round-audit-poam.json。本案整頁退役,只改一行導向新頁。「我的稽核」入口:MyAuditsView.vue(320 行)、/project/audit-manage、BE app/readmodel/service/auditor_dashboard_service.py+infra/readmodel/audit/auditor_dashboard_query.py(162 行);路由 seed 先例 scripts/sql/2026-04-27-add-audit-and-cloud-integration-permissions.sql:31-47。
FR-142 的頁面骨架、Excel 四頁(ap_workbook_*/ar_workbook_*)、匯入預覽模式;任務指派人 task_assignees(多人);退卡系統留言 not_met_redo_comment.build_redo_comment;任務到期提醒(FR-140 P4)不動。
| 畫面 | OSCAL | DB |
|---|---|---|
| 一條不符合評估目標 | poam-items[]:title/description 抄 finding、related-findings[{finding-uuid}]、related-risks[{risk-uuid}] |
oscal.poam_items(既有產生) |
| 稽核缺失(唯讀) | 從 AR 讀 finding、observation、risk、remediation lifecycle=recommendation;匯出時內嵌進 POA&M 檔 | 不重存 |
| 改善計畫(整組) | risk.remediations[] 一筆 lifecycle=planned、title=「改善計畫」 |
oscal.assessment_remediations |
| 一個任務的設定 | response.tasks[] 一筆:type=action、title=任務名、description=改善措施、timing.on-date.date=改善期限、responsible-roles[{role-id:'remediation-owner', party-uuids:[…]}]=執行人員、props[name=job-uid]=任務流程 uid |
oscal.poam_milestones:task_type=action、title、description、target_date、props.job_uid、props.assignee_user_ids[](多人全部進 props,assignee_user_id 存第一人向後相容) |
| 送出 | risk.status=remediating、risk.deadline=該項最晚改善期限;poams.status=submitted;同時寫回任務指派人、各站 due_at、系統留言 |
assessment_risks.status/deadline、oscal.poams.status、compliance.task_assignees、compliance.job_executions.due_at |
| 鎖定 | 以 poams.status 判 |
— |
官方必填:poam-item(title/description)、response(uuid/lifecycle/title/description)、task(uuid/type/title)、risk(uuid/title/description/statement/status)。執行人員對 party-uuid:專案參與者在 SSP metadata.parties 有對應 party(既有 matched_user_id),查不到的只寫 props(name)不寫 responsible-roles,不造假 uuid。mitigating-factors 留空(D11)。
匯出四處修正(棒 1):
| # | 現況 | 修法 |
|---|---|---|
| 1 | _milestone_to_task_json 沒帶 timing/responsible-roles |
補 timing.on-date.date=target_date、responsible-roles 反查 party-uuid |
| 2 | related-findings 塞私有鍵 finding-id(官方 additionalProperties:false) |
匯出剝掉;DB 繼續存 |
| 3 | POA&M 檔 findings[]/risks[]/observations[] 空,poam-item 引用懸空 |
匯出時把被引用的 finding、risk(含 remediations)、observation 寫進 POA&M 檔(同 uuid,組裝不複製 DB) |
| 4 | task 自創 status/completed_at |
不匯出;DB 欄不刪 |
掛在既有 /audit-round/<round_uid> 下,讀取以 FR-140「目前稽核次」取 POA&M(GET 可帶 pass)。新邏輯一律新檔 app/flow_control/service/poam_objective_app_service.py,不往套件 493 行的 poam_app_service.py 加。
| 方法 | 路徑 | 用途 |
|---|---|---|
| GET | …/poam/objectives |
只列不符合的控制項樹(族群→控制項→評估目標)、每條的稽核缺失(finding、risk、recommendation、稽核人員、查核方法、採用佐證)、底下的任務(流程 uid、名稱、原指派人、站數與狀態、目前設定:執行人員/改善期限/改善措施)、計畫狀態、統計六格、鎖定旗標 |
| PUT | …/poam/objective/<part_id> |
存一條評估目標底下全部任務的設定(陣列:job_uid、assignee_user_uids[]、due_date、advice);同一任務在別條評估目標也存在時一併套用;回傳該控制項最新狀態與統計 |
| POST | …/poam/submit |
守門(每個任務三欄齊,412 列「任務名 未填:X」)→ risk.status=remediating、deadline、poams.status=submitted → 寫回任務指派人與各站改善期限、系統留言 → 呼叫既有 close_round(內稽退卡走棒 5 的第一站重跑;外稽進待覆核)→ 鎖定 |
| GET | …/poam/export?format=xlsx|oscal |
匯出二選一 |
| POST | …/poam-xlsx/parse、/poam-xlsx/<parse_uid>/confirm |
Excel 匯入預覽與確認(棒 4) |
鎖定:送出後所有寫入端點回 409(新 error code GRC_POAM_SUBMITTED_LOCKED(「改善計畫已送出,內容不可修改」),GRC_409042(現有最大 409041))。權限:route 掛 grc.audit.read(讀)/grc.audit.update(寫,同既有 PoamMilestoneRoute);app service 內再以 common/authz 資源域守門要求專案 manager 才可寫,auditor 可讀。守門改法(棒 1):_close_on_pass 的 all_items_closed 改成 all_items_planned(每個 item 的每個 task 都有 target_date、assignee、description);GRC_POAM_NOT_ALL_CLOSED 文案改「尚有任務未完成規劃」。
任務對應:一條評估目標底下的任務=workflow_execution_control_mapping 對到該控制項(control_id)的流程;FR-141/142 已逐評估目標對應者取 ao_part_id,否則控制項層全部任務都算(與 FR-142 D8 佐證候選同源)。
照雛形 prototype/poam-authoring.html。FE 新檔 src/views/project/RoundPoamPlanView.vue+src/components/grc/poam/:PoamObjectiveTree.vue(左樹只列不符合、燈號已規劃/部分規劃/未規劃)、PoamControlOverview.vue、PoamObjectiveForm.vue(稽核缺失文件表單+任務區塊)、PoamTaskCard.vue(執行人員 chip 多選、改善期限、改善措施、帶入稽核建議)、PoamSubmitDialog.vue(守門清單/確認表)、PoamImportPreview.vue(預覽模式)。舊 RoundPoamView.vue 改一行導向新頁後退役。表單用語照雛形(稽核缺失、執行人員、改善期限、改善措施、已規劃/未規劃/待規劃),不放說明句(FR-142 D12 同)。禁 border-left ≥3px。
「改善計畫」頁只列判不符合的評估目標,一列一個任務;同一條評估目標的灰底欄合併儲存格、垂直置中,評估目標之間粗上框;凍結窗格在 S 欄:
| 欄 | 內容 | 匯入 |
|---|---|---|
| A(隱藏) | part_id | 比對鍵 |
| B~J(灰,合併) | FR-141 計畫欄:序號、控制項、實務要求、執行說明、評估目標、查核方法、受評人員、受評元件、稽核人員;D~J 群組預設收合 | 不讀 |
| K~Q(灰,合併) | FR-142 結果欄:稽核結果、佐證檔案、其他佐證、稽核發現、風險等級、風險說明、稽核建議 | 不讀 |
| R(隱藏) | job_uid | 比對鍵 |
| S~T(淺藍) | 任務、原指派人 | 不讀 |
| U(黃) | 執行人員:一格,多人以 ; 分隔;預設原指派人;必須是專案成員 |
讀 |
| V(黃) | 改善期限:YYYY-MM-DD,日期驗證;必填 |
讀 |
| W(黃) | 改善措施;必填 | 讀 |
「可選清單」頁只留「執行人員(專案成員)」。匯入預覽:異動列標黃、原值劃掉;執行人員對不到成員、日期格式不對、同一任務多列執行人員或改善期限不一致 → 標紅「待確認」就地處理;全部處理完才能確認。匯出名「改善計畫工作表(Excel)」。範例:prototype/sample/FR-143-改善計畫範例.xlsx(產生腳本 make_sample_xlsx.py)。
新檔 app/flow_control/service/job_restart_service.py:restart_from_first_station(workflow_execution_id, due_date, assignee_user_ids, curr_user):
get_latest_station_jobs),依 BPMN 順序找第一站。reopen_job_execution(進行中、清 end_time、通知);其餘站 status 改 TODO、清 end_time;流程 status 改 PROCESSING。due_at=due_at_from_milestone_date(due_date)、due_at_manual=false。task_assignees 改成執行人員清單(保留 is_approver 既有值);後續站不動。job_execution_redo_log(每站一筆)與系統留言(build_redo_comment,內容=改善措施)。not_met_job_redo_service.redo_not_met_jobs 改成逐 task 呼叫上式(來源從 earliest_milestone_dates 改讀 task 的 props.job_uid+target_date+props.assignee_user_ids)。launch_reverify 新任務:從第一站開始,due_at 與指派人同上。到期提醒(FR-140 P4)不動。
BE 新讀模型 app/readmodel/service/poam_dashboard_service.py+infra/readmodel/audit/poam_dashboard_query.py(照 auditor_dashboard_* 寫法):條件=登入者是該專案 manager、稽核次已結案且 POA&M 有 item;欄位見 D9;分頁、排序、篩選(狀態、稽核性質、標準、關鍵字)走後端。端點 POST /grc/poams/my/list(RequestMetaSchema)。FE 新頁 src/views/project/MyPoamsView.vue(表格,照 MyTasksView 的 lazy DataTable),路由 /project/poam-manage,名稱 poam-manage。路由 seed:scripts/sql/<日期>-fr143-poam-manage-route.sql(phase=seed:ui_routes 一列、route_capabilities 綁 grc.audit.* read=ALL,照 2026-04-27 先例);守衛 test/test_fr132_route_entry_registered.py 要過。
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
sequenceDiagram
participant PM
participant FE as 改善計畫頁
participant BE as BE/套件
participant Job as 任務流程
PM->>FE: 側邊選單「改善計畫」→ 點輪次
FE->>BE: GET /poam/objectives
BE-->>FE: 不符合評估目標:稽核缺失+底下任務
PM->>FE: 逐任務設執行人員、改善期限、改善措施,儲存
FE->>BE: PUT /poam/objective/<part_id>
PM->>FE: 送出改善計畫
FE->>BE: POST /poam/submit
BE->>BE: 守門:有任務沒填齊 → 412 列原因
BE->>BE: risk.status=remediating、poams.status=submitted、鎖定
BE->>Job: 每條流程:第一站回進行中且指派人=執行人員、後續站回待辦、每站 due_at=改善期限、系統留言、通知
BE->>BE: close_round(內部缺失改善站推進)
BE-->>FE: 已送出
外稽同前半段;送出後 close_round 走「母輪→pending_reverify」;launch_reverify 新任務從第一站開始、改善期限與指派人照計畫。
due_at 都是計畫日期(台北 23:59:59)、第一站 task_assignees 等於執行人員、主管檢核與顧問檢核的指派人不變、第一站有系統留言寫改善措施、執行人員收到通知;「我的任務」看到第一站帶改善期限。~/.claude/skills/oscal-knowledge/references/json-schemas/oscal_poam_schema.json 驗證通過;每個 task 有 timing.on-date 與 responsible-roles;related-findings 沒有 finding-id;findings[]/risks[] 非空。Notion:母卡 CM-2840;子卡 1=CM-2841、2=CM-2842、3=CM-2843、4=CM-2844、5=CM-2845、6=CM-2846、7=CM-2851。
| 卡 | 做什麼 | 碰哪裡 | 套件 | 依賴 | 驗收 |
|---|---|---|---|---|---|
| 1 | 匯出四處修正;all_items_closed→all_items_planned;task 存 props.job_uid/assignee_user_ids;earliest_milestone_dates/milestones_by_control 改回傳逐 task(job_uid、date、assignees、advice) |
pkg/jedi-oscal-v2/app/service/io/ 新 poam_export_parts.py;pkg/jedi-compliance-audit/app/service/poam_app_service.py(493)、audit_round_pass_transitions.py:96 |
兩支 | — | 驗收 7 |
| 2 | poam_objective_app_service.py+API、守門、鎖定、寫回任務、推進 |
app/flow_control/service/、api/project/routes/、api/project/__init__.py、common/code/ |
— | 1 | 驗收 2、3、4 的 API 部分 |
| 3 | FE 改善計畫頁 | FE src/views/project/RoundPoamPlanView.vue、src/components/grc/poam/、router、api.js、i18n |
— | 2 | 驗收 2、3、4 畫面部分 |
| 4 | Excel 一列一任務讀寫(合併、群組)、執行人員比對、預覽;FE 預覽模式 | app/flow_control/service/poam_workbook_*.py(新);FE PoamImportPreview.vue |
— | 1(FE 部分等 3) | 驗收 6 |
| 5 | job_restart_service.py;退卡改逐 task 第一站重跑、每站 due_at、指派人;覆核輪同 |
app/flow_control/service/not_met_job_redo_service.py(126)、新檔;pkg/jedi-compliance-audit/.../audit_round_app_service.py:543 launch_reverify |
jedi-compliance-audit | 1 | 驗收 5、8 |
| 6 | 入口清單讀模型、端點、FE 表格頁、路由 seed | app/readmodel/、infra/readmodel/audit/、api/、FE MyPoamsView.vue、scripts/sql/ |
— | 2 | 驗收 1 |
| 7 | 清單改依專案分組展開;useAuditWorkGroups 泛用化與稽核作業頁共用 |
FE MyPoamsView.vue、useAuditWorkGroups.js、my-poams.json |
— | 6 | 驗收 1 |
| # | 坑 | 影響 | 對策 |
|---|---|---|---|
| 1 | 現行退卡 pick_latest 只重開最新一站 |
多站流程退錯人;DEV 6 筆退卡紀錄全單站,測不出 | 棒 5 新 service 退第一站;驗收 5 用三站流程 |
| 2 | 期限只在站層,推出下一站不帶 | 後續站沒期限 | D12:退卡時全部站一次寫 |
| 3 | revert_job 帶操作者與輪次凍結守門 |
系統退卡直接呼叫會被擋 | 棒 5 另包,不呼叫 revert_job |
| 4 | oscal_io_service.py 1,697 行、audit_round_app_service.py 918 行、RoundPoamView.vue 890 行皆超標 |
不能往裡加 | 新開檔;原檔只加一行呼叫或退役 |
| 5 | task assignee_user_id 單值 |
多執行人員存不下 | props 存全部、欄位存第一人;匯出 responsible-roles 讀 props |
| 12 | 「任務」與「站」混用 | 雛形曾把三站畫成三塊,規格跟著寫錯 | 本文件「任務」一律指流程;站只唯讀顯示 |
| 6 | 執行人員對 party-uuid 查不到 | 匯出造假 uuid 不合規 | 查不到只寫 props 不寫 responsible-roles |
| 7 | 同一任務對多條評估目標 | 兩邊設定不一致 | PUT 時一併套用;Excel 多列不一致標待確認 |
| 8 | related-findings 私有鍵 finding-id |
官方 schema 驗證失敗 | 匯出剝掉,DB 留 |
| 9 | 送出後 PM 在抽屜改改善期限(FR-140 P5) | 計畫與任務漂移 | 維持 P5:手改標 manual、不回寫 POA&M;計畫鎖定不改 |
| 10 | 路由 seed 是 phase=seed,不是主線 active |
不需重產出貨基線 | 紀律段照實寫,runner 不要誤報 |
| 11 | 守門文案 GRC_POAM_NOT_ALL_CLOSED 被 FE i18n 引用 |
改文案要同步 FE | 棒 1 改 BE 文案、棒 3 同步 i18n |