本卡屬 FR-166(母卡 CM-3109 延伸),決策者 2026-10-28 裁 D23。主 repo(compliance-manager-be)+ jedi-remote-agent 套件(path dependency 開發、不發版)。FE 對話框改版是另一張卡,依賴本卡回傳的 capabilities 欄位,排下一批。
白話
現在管理員授權離線操作者時,要逐人勾「Agent 設定/Agent 檔案/獨立掃描/網路除錯」四個範圍,存在名單上;但同一個人從主系統點「連線至 Agent」時,範圍是主系統當下查他的能力點決定的。同一個人兩條路各算一次,主系統改了角色、名單上的勾選不會跟著變,決策者看了說「會亂掉」。
改成:權限只有一份,就是主系統的 Agent 能力點。離線名單只管「這個人能不能離線登入、授權到哪天」;每次心跳下發名單時,依該使用者當下持有的能力點算出範圍。主系統完全沒有 Agent 能力點的人,不能加進名單。
問題在哪
- jedi-remote-agent app/service/offline_operator_service.py:grant() 收 scope、_validate_scope() 要求非空、_authorize_user() 核「勾的範圍 ⊆ 本人能力點」,upsert 時把 scope 存進 remote_agent_offline_operators.scope(JSONB)。heartbeat_roster() 下發的是存著的 op.scope。_serialize() 回的也是存著的 scope。
- 主專案 api/remote_agent/routes/agent_offline_operator_route.py:OfflineOperatorGrantRequest.scope required=True。
- 宿主 core/plugins/_agent_offline_operators.py 已有 user_capabilities(user_id)(經 user_role_domain_service.get_active_capability_names,以當下 user context 的 tenant 查),心跳時是該 Agent 租戶的機器身分,同一支可直接用。
- 範圍↔能力點對照已有:jedi_remote_agent/plugin/contract.py 的 OFFLINE_OPERATOR_SCOPE_CAPABILITIES(四顆,刻意不含 restart,D14)。
怎麼做
- 【new 一支小函式】offline_operator_service 內 _scopes_for(user_id) -> list:user_capabilities(user_id) 對 OFFLINE_OPERATOR_SCOPE_CAPABILITIES 取交集,回排序後的範圍清單。roster、serialize、grant 三處都只呼叫這一支,不各寫一份。
- 【extend heartbeat_roster】每人的 scope 改成 _scopes_for(op.user_id),不讀 op.scope。算出來是空的(他在主系統的 Agent 能力點被拿光了)→ 照樣下發但帶 revoked: true,讓 Agent 踢掉他已登入的 session;不要直接不列(不列=Agent 那邊沿用舊快取的錯覺,見 heartbeat_offline 的註解)。
- 【extend grant】不再收 scope:簽名改 grant(agent_uid, user_id, expires_at, curr_user)。_authorize_user 改成「user 屬本租戶,且 _scopes_for(user_id) 非空」,空的回 403 新錯誤碼 OFFLINE_OPERATOR_NO_AGENT_CAPABILITY(訊息:該使用者在主系統沒有任何 Agent 權限,無法授權離線登入)。刪掉 _validate_scope 與 OFFLINE_OPERATOR_SCOPE_EXCEEDS_USER 的拋出點(錯誤碼常數留著不刪,FE i18n 可能還引用,grep 確認)。
- 【extend _serialize】scope 改回 _scopes_for(op.user_id)(給畫面顯示「離線時能做什麼」),另加 capabilities 鍵=同一份清單;FE 卡讀 capabilities。
- 【資料面】remote_agent_offline_operators.scope 欄位不刪、不寫 migration:upsert 時寫入當下算出的範圍當快照(給稽核看授權當時的樣子),但沒有任何讀取路徑再拿它判權限。model comment 改成「授權當下的範圍快照,判權限一律即時算」。
- 【extend 宿主路由】OfflineOperatorGrantRequest 拿掉 scope(schema 設 unknown=EXCLUDE,舊 FE 還送 scope 時不炸);route 呼叫新簽名。稽核事件 audit_operator_change 若有記 scope,改記算出來的範圍。
- 【不動】Agent 端(evidence-agent)只認名單上的 scope,不用改。入場券跳轉那條路不動。
改哪些檔
- ~/Projects/Jedicogy/module/jedi-python-package/jedi-remote-agent/jedi_remote_agent/app/service/offline_operator_service.py(138 行)、common/code(新錯誤碼)、infra/offline_operator/model/offline_operator.py(只改 comment)、tests/test_offline_operator_service.py、tests/test_heartbeat_offline.py
- api/remote_agent/routes/agent_offline_operator_route.py(104 行)、core/plugins/_agent_offline_operators.py(147 行,只在需要時動)