FR-040 稽核計畫填寫(ap-authoring)優化 — 換 session 交接

項目
緣由 AP 稽核計畫填寫頁優化:查核方法可擴充 + 行程(task)鉤稽控制項/受評對象/稽核人員
Branch(三 repo 都同名) FR-040-AP-improvement(BE / FE / jedi monorepo 皆是)
狀態 實作完成、單元測試綠、build 過、DEV DB 已遷移;但未經 user 手測驗收、未 push、套件未發版
接手前必讀 本檔 §0 讀序(design.md 全讀是硬 gate)
預估時間 驗收 0.5h;若做 Phase 7(說明改結構化 steps)+2~3h
環境關鍵 BE 要重啟;jedi_oscal_v2symlink勿跑 poetry install 會還原 pin 2.0.0 炸掉)

🧭 原始需求 / WHY(先讀,置頂)

稽核員在「稽核計畫填寫」頁(/project/projects/:id/round/:roundUid/ap-authoring)規劃一輪稽核。痛點與目標:

  1. 查核方法太少且寫死 → 改 system_menu(group AUDIT_METHOD)驅動,後台可增刪。
  2. 行程(task)跟控制項/對象/人員沒連結 → 讓一條行程能多對多鉤稽「要查哪些控制項 / 受評哪些對象(設備·系統·人員) / 哪些稽核人員執行」,外加時間與方法。
    • 使用者價值:受評單位看一條行程就知道「幾點、稽核方誰會來、要查什麼控制項、要準備/檢視哪些設備文件、我方誰要到場」,據此準備人與物。
  3. 受評方 vs 稽核方要分清楚(這是整個 arc 反覆釐清的核心):
    • 受評對象 = 受評方(被查的標的):系統元件、資產設備、SSP 內的人員/單位 → 來源 SSP partiesimport-ssp 帶入)。
    • 稽核人員 = 稽核方(執行的人,含外部稽核員)→ 來源 AP 自己的 metadata.parties,可在 AP 階段就地新增。

OSCAL 模型(已用官方範例 oscal-content/examples/ap/json/ifa_assessment-plan.json 證實,務必先懂)

assessment-plan
├── import-ssp                 → 受評方(SSP parties = 受評對象)
├── reviewed-controls          → 受評控制項母體(Tab1)
├── assessment-subjects        → 受評對象母體(Tab2)
├── metadata.parties + roles   → 稽核團隊(assessor)  ← 稽核人員在這!(非 SSP、非專案參與者)
├── local-definitions.activities → 一個「方法 + 一組控制項」的查核程序
│     └ related-controls(控制項) / props.method(方法) / steps(查核步驟)
└── tasks                      → 行程(timing)
      ├ associated-activities[].activity-uuid  → 引用 activity
      ├ subjects[]             → 該行程受評對象
      └ responsible-roles[]    → 該行程稽核人員(role-id=assessor + party-uuids)

1 task = 1 activity(本期 1:1)。method 放 activity.props(OSCAL 標準,非硬塞)。


§0 接手讀序(按序,前 3 個是「先懂需求」硬 gate)

  1. 🔒 本檔「🧭 原始需求」全讀 —— 不懂 受評方/稽核方 區別、OSCAL task→activity 模型,別碰 code。
  2. 🔒 docs/features/FR-040-2606-ap-authoring-improvement/design.md全讀,尤其 §4 儲存落點、§10 稽核人員=AP parties)
  3. 🔒 docs/analysis/2026-06-20-ap-task-control-subject-linkage.md(決策軌跡:為何 props/link 表/AP parties,被排除選項)
  4. docs/features/FR-040-2606-ap-authoring-improvement/implementation-plan.md(Phase 0~6 + Phase 7 提案)
  5. 主嫌路徑檔(見 §5)

冷接自檢 4 問(答不出回去讀)

  • (a) 受評對象 和 稽核人員 各從哪來、為什麼不同源?
  • (b) 一條行程的「控制項」存哪張表哪個欄?為什麼不是存 task?
  • (c) method 為什麼放 props 而不是開欄?
  • (d) 為什麼 BE 改套件不會炸但「跑 poetry install」會炸?

§1 現況(已完成 + 行為)

整個 FR-040 已 end-to-end 實作,分四塊:

1.1 查核方法 → system_menu(已上線於 DEV)

  • BE seed AUDIT_METHOD(6 法:檢視/訪談/測試/文件檢查/電腦設定比對/門禁系統設定比對)。
  • FE 下拉抓 GET /system/menu/AUDIT_METHOD,label 走 i18n(method_<value>)fallback DB key。

1.2 行程鉤稽控制項/受評對象/稽核人員(核心)

  • 控制項ap_assessment_activities.related_controls(profile in-scope,Tab1 子集)
  • 受評對象ap_task_subjects(新 link 表;Tab2 子集;下拉/chip 已依類型分組+小標)
  • 稽核人員 → AP metadata.partiesoscal.parties scope=ap.metadata_id),per-task 存 ap_task_participants;可「+新增」就地建 party(固定 person、role=assessor 隱藏、含 email/電話)
  • 方法ap_assessment_activities.props(name=method) / 時間ap_tasks.timing

1.3 行程 CRUD UI(已改)

卡片化:卡頭(序號+標題+類型+時間+刪)+ 卡身標籤式欄位(方法/控制項/受評對象/稽核人員/說明)。說明已改多行 Textarea。

1.4 DB(DEV 已套)

  • scripts/sql/2026-06-20-audit-method-menu.sql(AUDIT_METHOD seed)
  • scripts/sql/2026-06-21-fr040-ap-task-link-tables.sqloscal.ap_task_subjects / ap_task_participants
  • 稽核人員重用既有 oscal.parties/roles零新表

§2 前次教訓(本 arc 已踩,別重蹈)

  • 稽核人員資料源換過兩次:專案參與者(錯)→ SSP parties(錯,那是受評方)→ AP metadata.parties(正解)。別再退回專案參與者/SSP parties。
  • method/受評對象/稽核人員不要存自由文字:一律建真 entity 拿 uuid 再引用(OSCAL party uuid / control-id)。
  • role/party_type 過度暴露:稽核人員固定 person + role=assessor(UI 隱藏),別加回下拉除非 user 要多角色。
  • 過渡資料:commit 1e8c231(稽核人員=SSP parties)存過的行程,participants 是 SSP party uuid,在現行 AP-parties 下拉解析不到 → dev 重存即可。

§3 待辦 / 下一棒可能做的(非 bug,是 follow-up)

  1. 驗收(最優先):見 §6 手測 checklist。
  2. Phase 7(設計完成 design §11 + plan Phase 7,待 user 拍板實作):「說明」改結構化每方法查核指引(OSCAL activity.steps,step↔︎method 用 props 綁定,step.description=該方法看什麼怎麼看)。目前是多行 Textarea(commit 0103997)當過渡。欄位 ap_assessment_activities.steps 已存在、零新表。BE/FE 改動步驟見 design §11.6 / plan Phase 7。直接照 design §11 開工即可
  3. OSCAL 匯出(未做):mapper 把 ap_assessment_activities/ap_tasks/link 表/AP parties → OSCAL JSON(local-definitions.activities / task.subjects / responsible-roles / metadata.parties)。本期未做匯出。
  4. 收尾未做(等 user 驗收後下令):changelog、Notion 任務、push、套件發版。
  5. design §9 DEFERRED:AO/statement 層精準、行程↔︎活動 1:N。

§4 開工順位

  1. 跑 §6 pre-flight(branch/working tree/symlink/pytest/build)。
  2. 跑 §6 手測 checklist 驗收現況(這是 user 要的下一步)。
  3. 若做 Phase 7:先讀 design §10 + ap_assessment_activities model(steps 欄),再 FE 動態 per-method 指引欄 + BE set_tasks 寫 steps。
  4. 改完:BE 重啟提醒 user、給手測、等 user 下令才收尾/push

§5 該讀 / 會改的檔案

BE~/Projects/Billows/Audit-Manager/compliance-manager-be/

  • app/grc/service/assessment_plan_app_service.py — 核心:set_tasks(寫 activity+task+link)/_ap_detail(還原)/list_ap_parties/add_ap_party
  • api/project/routes/audit_round_route.pyApTasksRoute / ApPartiesRoute
  • api/project/serializers/audit_round.py_TaskItem / ApPartyAddRequest
  • test/test_fr040_ap_task_linkage.py — 9 測試(orchestration + AP party)

套件~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal-v2/

  • jedi_oscal_v2/infra/model/ap/oscal_ap_task_subjects.py / oscal_ap_task_participants.py(+ entity/mapper/repo 同名)
  • 稽核人員重用 oscal_party.py / party_repo_impl.py(metadata-scoped)

FE~/Projects/Billows/Audit-Manager/compliance-manager-fe/

  • src/views/project/RoundApAuthoringView.vue — Tab3 行程 UI + options + 新增 party dialog
  • src/config/locales/i18n/{zh-tw,en}/ap-authoring.json

§6 Pre-flight + 手測 checklist(可複製貼)

# branch / 乾淨度(三 repo 應都 FR-040-AP-improvement、clean)
for d in ~/Projects/Billows/Audit-Manager/compliance-manager-be ~/Projects/Billows/Audit-Manager/compliance-manager-fe ~/Projects/Jedicogy/module/jedi-python-package; do echo "== $d"; git -C "$d" branch --show-current; git -C "$d" status --short; done

# ⚠️ 套件 symlink 必須在(指向源碼,勿 poetry install)
ls -l ~/Projects/Billows/Audit-Manager/compliance-manager-be/.venv/lib/python3.11/site-packages/jedi_oscal_v2

# BE 單元測試(應 9 passed)
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && .venv/bin/python -m pytest test/test_fr040_ap_task_linkage.py -q

# FE build(應 exit 0)
cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe && npx vite build --mode development && rm -rf dist

手測(user 自己起服務;改 BE 後請 user 重啟)

  1. 進稽核計畫填寫頁 Tab「行程與方法」→ 新增行程 → 5 欄(方法/控制項/受評對象/稽核人員/說明)。
  2. 控制項 options = Tab1 勾選的;受評對象 = Tab2 的(下拉分組、chip 帶類型小標);稽核人員 = AP parties,點「+新增稽核人員」可就地建(姓名/email/電話)。
  3. 存檔 → 重整 → 應原樣還原。
  4. 切英文 label 正常;說明可多行。

§7 環境 / 部署狀態

  • DEV DB 已套 兩支 migration + AUDIT_METHOD seed;STG/POC/PROD 未套
  • jedi_oscal_v2 = symlink(site-packages → 源碼),BE 重啟即用新碼;原 pin 備份 jedi_oscal_v2.pinbakpoetry install(會還原 pin 2.0.0、缺新表 model → BE 炸)。
  • 未 push(三 repo);套件未 bump version / 未發 Nexus(部署前流程:套件 bump+發 Nexus → BE pin 新版 → poetry update → 各環境跑 migration)。

§8 行為規範提醒

  • 不切 branch(三 repo 已在 FR-040-AP-improvement);不自動 push(等 user)。
  • 改 BE service → 提醒 user 重啟。
  • 改套件走 symlink/path dep,發版等 user 明示。
  • 跨 repo 各自 commit、顯式 git add、禁 -am
  • changelog/Notion/SUMMARY 等收尾 → 等 user 驗收 + 下令才做
  • 不晶晶體;plan 假設先 verify。

§9 本 arc commits(branch FR-040-AP-improvement,均未 push)

BE(FR-040 相關,新→舊):e1131c31(person+email/phone) 27ed00cb(Phase6 AP parties) 12189f38(B design) 6286db0e(源更正) f09d71a2(DONE-verify handoff) 7fb60037(set_tasks 鉤稽) 5d05a5da(design/plan/analysis) 8de251b6(AUDIT_METHOD seed) eae77461(vw_user_job_queue 控制群組,順手修)

註:同 branch 另有 b1211299/e0041bfd/cf4e68f7/3814c57c/e8a2666a 是 FR-038/FR-039 的早期修正,非 FR-040。

FE0103997(說明多行) 0e780e6(chip 類型小標+去角色) 9861654(受評對象分組) e1ca5aa(party person+email/phone) ea42fa4(隱藏 role) e614b56(Phase6 AP parties) 1e8c231(過渡:SSP parties,已被取代) 1996432(名稱修+改名稽核人員) d043fcf(卡片化 UI) d955f7d(鉤稽) f1b2052(method system_menu) 27c66a1/6282fb0/ce3b810(早期 dashboard/輪次 fix,非 FR-040)

套件8684658(ap_task_subjects/participants link 表)


§10 不在本期 scope(別順手做)

  • OSCAL 匯出/匯入 mapper(Phase 7 之後再議)
  • AO/statement 層控制項精準
  • 行程↔︎活動 1:N
  • 稽核人員多角色下拉(現固定 assessor)
  • 受評對象就地新增(目前只能從 Tab2 選;只有稽核人員支援就地新增)

§11 給 fresh session 的超短 prompt

接手 FR-040「稽核計畫填寫優化」。請先讀
docs/features/FR-040-2606-ap-authoring-improvement/handoff/2026-06-21-FR040-ap-authoring-handoff.md
全文(尤其「🧭 原始需求」+ §0 讀序 + design.md 全讀),答得出 §0 冷接自檢 4 問再動工。
現況:已實作完成、未驗收、未 push、套件走 symlink(勿 poetry install)。
先跑 §6 pre-flight + 手測 checklist 驗收;要做 Phase 7(說明改結構化 steps)等我確認。
不切 branch、不自動 push、收尾等我下令。