本卡屬 FR-088(母卡見 FR-088 母案),第 4 棒 H3:主專案的流程範本 CRUD/複製/發布/驗證端點與凍結副本服務(BE repo)。只掃不修。
管理者可以在畫面上建立、修改、複製、發布自己公司的稽核流程範本,也能看原廠內建的範本。這一棒掃的是這組管理功能的 13 檔:誰能改誰的範本、存進去的流程圖有沒有先檢查、原廠範本會不會被客戶改掉、每輪稽核凍結的那份副本歸誰。只找問題、不修問題。
這是本 arc 唯一資料庫隔離是開的一組(flow_templates relrowsecurity=t、4 條規則,DEV 實查)——正好可以驗證「隔離開了之後應用層還有沒有洞」。同時它是惡意 XML 進系統的入口(建立、更新、驗證三個端點都收 XML)。
行號已開檔核對,是思考起點不是檢查清單:
app/flow_engine/service/flow_template_app_service.py:69-84 create() 只查名字重複就存;:87-108 update() XML 變了只把狀態改回 draft;解析只在 publish()(:110-120)做。存進去的壞 XML 會在哪些地方被讀到(列表 include_xml=False、單筆 include_xml=True、複製、凍結副本、AI 儀表板?)——找出「存了壞 XML 之後誰會炸」。validate 端點對任何登入者開放任意 XML 解析:api/flow_engine/routes/flow_template_route.py:130-144 只掛 jwt_required(無能力檢查,FE 拖線時 debounce 呼叫),service :143-157 直接 BpmnTopologyValidator(rules).validate(xml) → BpmnUtils(xml)。無次數限制。與 FR-082 A1(AI 聊天無限制)同型的資源耗盡面,門檻只要登入。flow_template_route.py:20-26 三個 decorator(create/update/delete)精準對 verb;get(列表 :32-45、單筆 :61-66)只有 jwt_required。列表 :48 在 app 層加了 tenant_id=ctx.tenant_id,單筆走 _require_active → get_by_uid(infra/flow_engine/repository/flow_template_repo_impl.py:51-53)只 filter_by(uid, is_active),靠 RLS 擋跨租戶。要驗:RLS 的 4 條規則對 cmmgr/cm_app 各是什麼、平台管理員(root 租戶)是不是「上層看下層」的合法路徑。flow_template_app_service.py:187-197 _guard_builtin_writable() 只在 update/publish/unpublish/soft_delete 四處呼叫(:90/:112/:126/:138),用 viewer_is_platform_admin()。duplicate()(:159-177)把內建範本複製到自己租戶——這是刻意的。要驗:有沒有任何一條寫入路徑漏掉這個守門(例如 validate 不寫、create 不會碰內建)。app/flow_engine/service/workflow_template_snapshot_service.py:74-85 呼叫套件 add_workflow_template(...) 沒傳 tenant_id,寫進 compliance.workflow_templates(不是 flow_templates)。這正是 FR-087 §5.2 查到的 191 筆無主凍結副本的來源。本棒要答:套件 model 的 TenantScopedMixinModel 為什麼沒自動補上(背景任務無 context?__skip_auto_tenant__?)——這決定「打開 workflow_templates 隔離」之前要回填多少。flow_template_repo_impl.py:44 ilike(f"%{query.name_like}%")——ORM 綁參數應該安全,但 %/_ 通配字元未跳脫可讓一個請求掃全表;記錄即可。app/flow_engine/dto/flow_template_dto.py 單筆回 include_xml=True 含整份 XML 與 created_user/updated_user;確認有沒有夾帶不該回的欄位(與 FR-083 D1 F2「整包原樣回傳」同型)。_guard_builtin_writable 的由來。workflow_templates 191 筆凍結副本 tenant 空、132 筆仍連著使用中的流程——本棒查的是為什麼會空,不是重數。flow_template.create/update/delete。