卡片 CM-2513(FR-132 T-1.3)。唯讀盤點,不改程式、不改 DB。
asset)、遠端代理(remote-agent-manage)、檢測工具外掛與執行(plugin)、檢測基準(detection-profile)、授權掃描網段(scan-zone)、雲端整合(cloud_integration)、AI 證據分類(jedi-evidence-classification)、儲存設定(storage-config)與檔案上傳下載(jedi-file-upload)、問卷(survey)。api/cloud_integration/routes/ 4 支(13)、api/remote_agent/routes/agent_file_route.py(1)、api/system_config/routes/system_config_route.py 中屬 storage-config 的 2 個 Resource(3;該檔其餘端點屬 T-1.4)。.venv/lib/python3.11/site-packages/ 內實際執行的版本(jedi-detection 1.2.7、jedi-remote-agent 1.4.0、jedi-asset 1.2.2、jedi-evidence-classification 1.6.2、jedi-file-upload 1.3.4、jedi-survey 1.2.3)。/system/config/*(jedi-system-core)雖會依 GROUP 守 storage-config.*,屬 T-1.4 範圍,本卡只記它的分流規則不逐支列。localhost:5432/guidant_ai_dev)。範圍內舊能力點 30 個(8 種 resource_type)。storage-config.update(見第 5 點)。grc.job,不放 detection——放 detection 會讓「買了檢測包、但公司角色沒勾 detection」的稽核員在任務頁按開始掃描時 403。見文末定案結論。remote-agent-manage.create,連列表都是。原因是套件只給一個 admin_required 插槽、不分讀寫(core/plugins/remote_agent.py:147-168)。改名時要麼請套件拆成讀寫兩欄,要麼宿主自掛 route;不拆的話新名四個動詞只有一個有作用。survey.response,歸 grc.job.read/update(見文末定案 2)。storage-config.* 一顆鑰匙開了五扇門:儲存設定頁、Google 應用程式憑證頁、AI 服務設定頁、支援頁、AI 證據分類設定(套件寫入端借 storage-config.update)。拆不拆、歸哪個模組都見文末定案結論,建議見「storage-config 歸屬建議」。| 新資源 | read | create | update | delete | 獨立動詞 | 取代的舊名 |
|---|---|---|---|---|---|---|
asset.device |
✓ | ✓ | ✓ | ✓ | import、export |
device.* |
detection.remote-agent |
✓ | ✓ | ✓ | ✓ | — | remote-agent-manage.* |
detection.plugin |
✓ | ✓ | ✓ | ✓ | — | plugin.* |
detection.profile |
✓ | ✓ | ✓ | ✓ | — | detection-profile.* |
detection.scan-zone |
✓ | ✓ | ✓ | ✓ | — | scan-zone.read/update |
evidence.cloud-integration |
✓ | ✓ | ✓ | ✓ | — | cloud_integration.* |
evidence.classification |
✓ | ✓ | ✓ | ✓ | — | 無(新開) |
system.storage-config |
✓ | ✓ | ✓ | ✓ | — | storage-config.* |
evidence.classification-profile |
✓ | ✓ | ✓ | ✓ | — | 借用 storage-config.update(拆出) |
ai.ai-provider-config |
✓ | ✓ | ✓ | ✓ | — | 借用 storage-config.*(拆出) |
survey.survey |
✓ | ✓ | ✓ | ✓ | import、publish |
survey.* |
detection.profile 不叫 detection.detection-profile:模組名已是 detection,資源段重複前綴只是噪音。detection.scan-zone、detection.remote-agent 同理把 -manage 拿掉(manage 是頁名,不是資源)。evidence.cloud-integration 用連字號:舊名 cloud_integration 是底線,三段式規定資源段內用連字號。license 鍵仍是 cloud_integration(D10 的 license_module 欄存原值),授權照不受影響。survey.survey 兩段同名,但資源段要有值;若 T-1.6 合併時傾向 survey.questionnaire,主表照換即可。survey.response:填答端歸 grc.job.read/update(通則 A,見文末定案 2)。detection.scan-zone 補 create/delete:今天只有 read/update 兩顆,新增與刪除都掛 update。依「固定四個」規則補齊,route 改守對應動詞。欄位:route 路徑 | HTTP | 程式位置 | 現有守門 | 新三段名 | 現有能力點 | 對應 UI | 可指派範圍層 | 備註。
守門縮寫:J=jwt_required;L(x)=授權照守門 require_license("x");C(x)=能力點守門;PA=平台管理員;成員:=專案層角色檢查(參與者=任何成員)。所有路徑前綴 /api/1.0。套件 route 檔的路徑以 jedi_xxx/api/routes/ 起算。
jedi-asset 的 route 守門:auth_required(宿主注入的 jwt)+capability_required(rt.config.device_*_capability),能力點名預設值在 jedi_asset/plugin/contract.py:77-80。無授權照守門(設備屬基礎包)。
| route 路徑 | HTTP | 程式位置 | 現有守門 | 新三段名 | 現有能力點 | 對應 UI | 範圍層 | 備註 |
|---|---|---|---|---|---|---|---|---|
/devices |
POST | jedi_asset/api/routes/device_route.py:39 |
J+C(device.read) | asset.device.read |
device.read |
DeviceManage(/device/device-manage) |
org_unit | 列表 |
/devices/menu |
GET | device_route.py:59 |
J+C(device.read) | 跟呼叫頁面的權限(通則 B) | device.read |
ModuleFrameSspDevicesPanel、JobExecutionDrawer(useDeviceTargetOptions) |
org_unit | 輔助端點 |
/device |
POST | device_route.py:129 |
J+C(device.create) | asset.device.create |
device.create |
DeviceManage |
org_unit | |
/device/<uid> |
GET | device_route.py:72 |
J+C(device.read) | asset.device.read |
device.read |
DeviceManage |
org_unit | |
/device/<uid> |
PUT | device_route.py:82 |
J+C(device.update) | asset.device.update |
device.update |
DeviceManage |
org_unit | |
/device/<uid> |
DELETE | device_route.py:94 |
J+C(device.delete) | asset.device.delete |
device.delete |
DeviceManage |
org_unit | |
/device/<uid>/references |
GET | device_route.py:111 |
J+C(device.read) | asset.device.read |
device.read |
DeviceManage(刪除前警示) |
org_unit | 輔助端點 |
/devices/import-template |
GET | jedi_asset/api/routes/device_import_route.py:50 |
J+C(device.create) | asset.device.import |
device.create |
DeviceImportDialog |
org_unit | 匯入類獨立動詞 |
/devices/import/verify |
POST | device_import_route.py:65 |
J+C(device.create) | asset.device.import |
device.create |
DeviceImportDialog |
org_unit | |
/devices/import/confirm |
POST | device_import_route.py:82 |
J+C(device.create) | asset.device.import |
device.create |
DeviceImportDialog |
org_unit | FE 該元件另判 hasCap('device.update'),與 BE 守的 create 不一致 |
/devices/export |
POST | device_import_route.py:102 |
J+C(device.read) | asset.device.export |
device.read |
DeviceExportMenu |
org_unit | 對外送出類獨立動詞;今天有 read 就能匯出 |
主專案另有兩處拿 device.read 判斷:app/module_frame/service/template_lookup_scope.py:16(沒有就不給設備 IP)、di_containers/dashboard_apis/device.py:19(儀表板資料源)。
套件 jedi_remote_agent/api/routing.py:15-62 的路由表第三欄宣告每支的認證等級;管理端點(AUTH_ADMIN)由宿主的 admin_required 套上,內容是 J+L(remote-agent-manage)+C(remote-agent-manage.create)(core/plugins/remote_agent.py:147-168)。代理呼入的控制面端點驗代理通行證,不帶使用者身分。
| route 路徑 | HTTP | 程式位置 | 現有守門 | 新三段名 | 現有能力點 | 對應 UI | 範圍層 | 備註 |
|---|---|---|---|---|---|---|---|---|
/remote-agents |
GET | jedi_remote_agent/api/routes/remote_agent_route.py:58 |
J+L(remote-agent-manage)+C(remote-agent-manage.create) | detection.remote-agent.read |
remote-agent-manage.create |
ToolPluginManage、StorageConfigForm、ProjectPlanningView(代理下拉) |
tenant | 輔助端點(啟用中的代理下拉);見下方「跨頁下拉」 |
/remote-agents |
POST | remote_agent_route.py:66 |
同上 | detection.remote-agent.create |
同上 | RemoteAgentManage(/system/remote-agent-manage) |
tenant | |
/remote-agents/all |
GET | remote_agent_route.py:90 |
同上 | detection.remote-agent.read |
同上 | RemoteAgentManage |
tenant | 管理頁列表(含停用) |
/remote-agents/health-check |
POST | remote_agent_route.py:75 |
同上 | detection.remote-agent.read |
同上 | RemoteAgentManage |
tenant | 只讀狀態,不改資料 |
/remote-agents/<uid>/reconcile |
POST | remote_agent_route.py:82 |
同上 | detection.remote-agent.update |
同上 | RemoteAgentManage |
tenant | 對帳會改雲端錨點狀態 |
/remote-agents/<uid> |
GET | remote_agent_route.py:98 |
同上 | detection.remote-agent.read |
同上 | RemoteAgentManage |
tenant | |
/remote-agents/<uid> |
PUT | remote_agent_route.py:105 |
同上 | detection.remote-agent.update |
同上 | RemoteAgentManage |
tenant | 含啟用/停用 |
/remote-agents/<uid> |
DELETE | remote_agent_route.py:112 |
同上 | detection.remote-agent.delete |
同上 | RemoteAgentManage |
tenant | |
/remote-agents/<uid>/revoke |
POST | remote_agent_route.py:119 |
同上 | detection.remote-agent.update |
同上 | RemoteAgentManage |
tenant | 狀態轉換但非四類獨立動詞之一 |
/remote-agents/<uid>/unrevoke |
POST | remote_agent_route.py:127 |
同上 | detection.remote-agent.update |
同上 | RemoteAgentManage |
tenant | |
/remote-agents/<uid>/approve |
POST | remote_agent_route.py:135 |
同上 | detection.remote-agent.update |
同上 | RemoteAgentManage |
tenant | 見文末定案結論:核准新報到代理是否開 approve 獨立動詞(見文末定案結論) |
/remote-agents/<uid>/rebind |
POST | remote_agent_route.py:144 |
同上 | detection.remote-agent.update |
同上 | RemoteAgentManage |
tenant | |
/agents/enroll-token |
GET | remote_agent_route.py:154 |
同上 | detection.remote-agent.read |
同上 | RemoteAgentManage |
tenant | 只回摘要 |
/agents/enroll-token |
POST | remote_agent_route.py:160 |
同上 | detection.remote-agent.create |
同上 | RemoteAgentManage |
tenant | 產生註冊 token,明文只回一次 |
/agents/enroll-token/revoke |
POST | remote_agent_route.py:168 |
同上 | detection.remote-agent.delete |
同上 | RemoteAgentManage |
tenant | 停用所有註冊 token |
/agents/register |
POST | remote_agent_route.py:177 |
註冊 token(AUTH_ENROLL) |
豁免 | 無 | 無 UI(代理呼入) | — | 代理用註冊 token 換通行證,刻意不設使用者守門 |
/agents/heartbeat |
POST | remote_agent_route.py:187 |
代理通行證 | 豁免 | 無 | 無 UI | — | 代理呼入 |
/agents/tasks/<uid>/ack |
POST | remote_agent_route.py:194 |
代理通行證 | 豁免 | 無 | 無 UI | — | 代理呼入 |
/agents/tasks/<uid>/result |
POST | remote_agent_route.py:200 |
代理通行證 | 豁免 | 無 | 無 UI | — | 代理呼入 |
/agents/files/<uid> |
GET | 主專案 api/remote_agent/routes/agent_file_route.py:40 |
代理通行證+任務綁定驗證 | 豁免 | 無 | 無 UI | — | 宿主自掛(core/plugins/remote_agent.py:224-233),代理下載任務源碼包 |
套件路由表 15 條路徑、19 個 method(管理 15、代理呼入 4),加主專案宿主自掛 1 支。
跨頁下拉:GET /remote-agents 被三個非代理管理頁拿來當下拉(工具外掛設定、儲存設定、專案規劃的檢測任務)。今天要 remote-agent-manage.create 才拿得到,等於「會設儲存的人一定要有代理建立權」。新名掛 detection.remote-agent.read 後,出貨角色範本要確認儲存設定管理人與專案規劃者都帶這顆 read。
jedi-detection 所有 route 都由 jedi_detection/api/routing.py:175-192 的動態子類套上宿主的 jwt_required(core/plugins/detection.py:388),再加各自的 L 與 C。能力點名預設在 jedi_detection/plugin/contract.py:32-54。
| route 路徑 | HTTP | 程式位置 | 現有守門 | 新三段名 | 現有能力點 | 對應 UI | 範圍層 | 備註 |
|---|---|---|---|---|---|---|---|---|
/detection-tools |
GET | jedi_detection/api/routes/detection_tool_route.py:31 |
J+L(plugin) | detection.plugin.read ∣ grc.job.read |
無 | ToolPluginManage(/plugin/tool-plugin-manage)、DetectionProfileManageView、JobExecutionDrawer(只在任務綁工具時) |
tenant | 工具目錄(全域字典、不含憑證) |
/detection-tools/<uid> |
GET | detection_tool_route.py:43 |
J+L(plugin) | detection.plugin.read |
無 | 同上 | tenant | |
/detection-tools/configs |
GET | detection_tool_route.py:56 |
J+L(plugin) | detection.plugin.read |
無 | ToolPluginManage、ProjectPlanningView |
tenant | 租戶工具設定列表 |
/detection-tools/configs |
POST | detection_tool_route.py:70 |
J+L(plugin)+C(plugin.update) | detection.plugin.create |
plugin.update |
ToolPluginManage |
tenant | 今天建立守 update |
/detection-tools/configs/<uid> |
PUT | detection_tool_route.py:91 |
J+L(plugin)+C(plugin.update) | detection.plugin.update |
plugin.update |
ToolPluginManage |
tenant | |
/detection-tools/configs/<uid>/reset |
POST | detection_tool_route.py:108 |
J+L(plugin)+C(plugin.update) | detection.plugin.update |
plugin.update |
ToolPluginManage |
tenant | 清空憑證 |
/detection-tools/configs/<uid>/test-connection |
POST | detection_tool_route.py:132 |
J+L(plugin)+C(plugin.update) | detection.plugin.update |
plugin.update |
ToolPluginManage |
tenant | 會解密憑證送往主機,必須維持寫入級 |
/detection-tools/configs/<uid>/referencing-tasks-count |
GET | detection_tool_route.py:152 |
J+L(plugin) | detection.plugin.read |
無 | ToolPluginManage |
tenant | 輔助端點 |
/detection-tools/<uid>/param-schema |
GET | detection_tool_route.py:165 |
J+L(plugin) | grc.job.read |
無 | JobExecutionDrawer |
tenant | 輔助端點;任務設置畫面用 |
/detection-tools/jobs/<job_uid>/execute |
POST | detection_tool_route.py:186 |
J+L(plugin);成員:任務操作人 | grc.job.update |
無 | JobExecutionDrawer |
org_unit | 見文末定案結論:歸 grc.job(見文末定案結論) |
/detection-tools/jobs/<job_uid>/cancel |
POST | detection_tool_route.py:218 |
同上 | grc.job.update |
無 | JobExecutionDrawer |
org_unit | 同上 |
/detection-tools/jobs/<job_uid>/executions |
GET | detection_tool_route.py:354 |
J+L(plugin);成員:參與者 | grc.job.read|grc.job-evidence.read |
無 | JobExecutionDrawer |
org_unit | 同上 |
/detection-tools/execution-groups/<g>/assignments/<a>/rerun |
POST | detection_tool_route.py:237 |
J+L(plugin);成員:任務操作人 | grc.job.update |
無 | JobExecutionDrawer |
org_unit | 同上 |
/detection-tools/execution-groups/<g>/assignments/<a>/cancel |
POST | detection_tool_route.py:258 |
同上 | grc.job.update |
無 | JobExecutionDrawer |
org_unit | 同上 |
/detection-tools/execution-groups/<g>/assignments/<a>/start-now |
POST | detection_tool_route.py:279 |
同上 | grc.job.update |
無 | JobExecutionDrawer |
org_unit | 同上 |
/detection-tools/execution-groups/<g>/cancel |
POST | detection_tool_route.py:299 |
同上 | grc.job.update |
無 | JobExecutionDrawer |
org_unit | 同上 |
/detection-tools/execution-groups/<g> |
DELETE | detection_tool_route.py:335 |
同上 | grc.job.update |
無 | JobExecutionDrawer |
org_unit | 只能刪全失敗的群組;清理執行紀錄,不是刪任務 |
/detection-tools/executions/<uid> |
DELETE | detection_tool_route.py:317 |
同上 | grc.job.update |
無 | JobExecutionDrawer |
org_unit | 同上 |
「任務操作人」=assert_job_operator(jedi_detection/app/service/detection_orchestration_service.py:209,913,969,1061,1090,1159,1189,1532),列表走 assert_project_participant(:1736),實作由宿主的流程執行 service 注入。
守門 _profile_read/_create/_update/_delete 定義在 jedi_detection/api/routes/detection_profile_route.py:58-61。分類字典 4 個寫入端點走平台管理員(全域字典表)。
| route 路徑 | HTTP | 程式位置 | 現有守門 | 新三段名 | 現有能力點 | 對應 UI | 範圍層 | 備註 |
|---|---|---|---|---|---|---|---|---|
/detection-tool-profiles/list |
POST | detection_profile_route.py:141 |
J+L(detection-profile)+C(read) | detection.profile.read |
detection-profile.read |
DetectionProfileManageView(/plugin/detection-profile-manage) |
tenant | |
/detection-tool-profiles/menu |
GET | detection_profile_route.py:170 |
同上(read) | detection.profile.read |
detection-profile.read |
JobExecutionDrawer(useDetectionProfileOptions) |
tenant | 輔助端點 |
/detection-tool-profiles |
POST | detection_profile_route.py:191 |
同上(create) | detection.profile.create |
detection-profile.create |
DetectionProfileManageView、ProfileFormDialog |
tenant | |
/detection-tool-profiles/<uid> |
GET | detection_profile_route.py:219 |
同上(read) | detection.profile.read |
detection-profile.read |
同上 | tenant | |
/detection-tool-profiles/<uid> |
PUT | detection_profile_route.py:238 |
同上(update) | detection.profile.update |
detection-profile.update |
同上 | tenant | |
/detection-tool-profiles/<uid> |
DELETE | detection_profile_route.py:266 |
同上(delete) | detection.profile.delete |
detection-profile.delete |
同上 | tenant | |
/detection-tool-profiles/<uid>/versions |
GET | detection_profile_route.py:283 |
同上(read) | detection.profile.read |
detection-profile.read |
ProfileVersionTable |
tenant | |
/detection-tool-profiles/<uid>/referencing-usage |
GET | detection_profile_route.py:313 |
同上(read) | detection.profile.read |
detection-profile.read |
useProfileUsage |
tenant | 輔助端點 |
/detection-tool-profiles/<uid>/new-version |
POST | detection_profile_route.py:421 |
同上(create) | detection.profile.create |
detection-profile.create |
ProfileVersionTable |
tenant | 版更算建立新一版 |
/detection-tool-profiles/<uid>/fork |
POST | detection_profile_route.py:450 |
同上(create) | detection.profile.create |
detection-profile.create |
ProfileCopyDialog |
tenant | 跨資源動作歸被產出的資源 |
/detection-tool-profiles/<uid>/copy-to-tool |
POST | detection_profile_route.py:471 |
同上(create) | detection.profile.create |
detection-profile.create |
ProfileCopyDialog |
tenant | 同上 |
/detection-tool-profiles/<uid>/deactivate |
PUT | detection_profile_route.py:495 |
同上(delete) | detection.profile.delete |
detection-profile.delete |
DetectionProfileManageView |
tenant | 停用守 delete(套件設計:停用即「下架」) |
/detection-tool-profile-versions/<uid>/controls |
GET | detection_profile_route.py:519 |
同上(read) | detection.profile.read |
detection-profile.read |
ProfileVersionTable |
tenant | |
/detection-tool-profile-versions/<uid>/extraction |
GET | detection_profile_route.py:540 |
同上(read) | detection.profile.read |
detection-profile.read |
同上 | tenant | |
/detection-tool-profile-versions/<uid>/extraction |
POST | detection_profile_route.py:555 |
同上(create) | detection.profile.create |
detection-profile.create |
同上 | tenant | 手動重抽 |
/detection-tool-profile-versions/<uid>/referencing-usage |
GET | detection_profile_route.py:339 |
同上(read) | detection.profile.read |
detection-profile.read |
useProfileUsage |
tenant | 輔助端點 |
/detection-tool-profile-versions/<uid>/source |
PATCH | detection_profile_route.py:370 |
同上(create) | detection.profile.create |
detection-profile.create |
ProfileSourceDialog |
tenant | 補來源檔 |
/detection-tool-profile-versions/<uid> |
DELETE | detection_profile_route.py:403 |
同上(delete) | detection.profile.delete |
detection-profile.delete |
ProfileVersionTable |
tenant | |
/detection-profile-taxonomies |
GET | jedi_detection/api/routes/detection_profile_taxonomy_route.py:62 |
J+L(detection-profile) | detection.profile.read |
無 | useProfileTaxonomy(基準表單下拉) |
tenant | 輔助端點 |
/detection-profile-taxonomies |
POST | detection_profile_taxonomy_route.py:84 |
J+L+PA | 平台層(T-1.5) | 無 | useProfileTaxonomy |
— | 全域字典,平台管理員維護 |
/detection-profile-taxonomies/<uid> |
PUT | detection_profile_taxonomy_route.py:111 |
J+L+PA | 平台層 | 無 | 同上 | — | |
/detection-profile-taxonomies/<uid> |
DELETE | detection_profile_taxonomy_route.py:135 |
J+L+PA | 平台層 | 無 | 同上 | — | |
/detection-profile-taxonomies/<uid>/referencing-profiles-count |
GET | detection_profile_taxonomy_route.py:150 |
J+L(detection-profile) | detection.profile.read |
無 | 同上 | tenant | 輔助端點 |
detection_profile_route.py 18 個、detection_profile_taxonomy_route.py 5 個。另外 core/plugins/_file_ownership.py:224-225 用 detection-profile.read/delete 判基準來源檔的下載與刪除權,改名要一起動。
基礎設施豁免:scan-zone 在 common/authz/license.py:107-121 的 INFRASTRUCTURE_MODULES,授權照守門恆放行。仍要歸模組:它是檢測的安全邊界,只有買了檢測包才有意義,歸 detection。
| route 路徑 | HTTP | 程式位置 | 現有守門 | 新三段名 | 現有能力點 | 對應 UI | 範圍層 | 備註 |
|---|---|---|---|---|---|---|---|---|
/scan-zones |
GET | jedi_detection/api/routes/scan_zone_route.py:38 |
J+L(scan-zone,豁免)+C(scan-zone.read) | detection.scan-zone.read |
scan-zone.read |
ScanZoneManage(/system/scan-zone) |
tenant | |
/scan-zones |
POST | scan_zone_route.py:47 |
同上+C(scan-zone.update) | detection.scan-zone.create |
scan-zone.update |
同上 | tenant | 補四動詞後改守 create |
/scan-zones/<uid> |
PUT | scan_zone_route.py:60 |
同上+C(update) | detection.scan-zone.update |
scan-zone.update |
同上 | tenant | 含確認 pending 建議 |
/scan-zones/<uid> |
DELETE | scan_zone_route.py:70 |
同上+C(update) | detection.scan-zone.delete |
scan-zone.update |
同上 | tenant | 補四動詞後改守 delete |
/scan-zones/suggest-from-agents |
POST | scan_zone_route.py:81 |
同上+C(update) | detection.scan-zone.create |
scan-zone.update |
同上 | tenant | 產生 pending 建議列 |
FE 常數在 src/config/scanZone.js(SCAN_ZONE_READ/SCAN_ZONE_UPDATE),改名要一起動。
主專案 api/cloud_integration/__init__.py 掛載,前綴 /api/1.0。
| route 路徑 | HTTP | 程式位置 | 現有守門 | 新三段名 | 現有能力點 | 對應 UI | 範圍層 | 備註 |
|---|---|---|---|---|---|---|---|---|
/integrations/google-drive |
GET | api/cloud_integration/routes/google_drive_integration_route.py:56 |
J+L(cloud_integration) | evidence.cloud-integration.read |
無 | GoogleDriveIntegrationCard(/settings/cloud-integrations)、ProjectListView、ProjectPlanningView、ProjectAuditorOverview |
tenant | 刻意不掛 read(:49 註解:專案頁的一般成員要看連線狀態);見文末定案結論 |
/integrations/google-drive |
DELETE | google_drive_integration_route.py:71 |
J+L+C(cloud_integration.delete) | evidence.cloud-integration.delete |
cloud_integration.delete |
GoogleDriveIntegrationCard |
tenant | 中斷連線 |
/integrations/google-drive/auth-url |
POST | google_drive_integration_route.py:90 |
J+L+C(cloud_integration.create) | evidence.cloud-integration.create |
cloud_integration.create |
GoogleDriveIntegrationCard |
tenant | |
/integrations/google-drive/callback(DRIVE_CALLBACK_ROUTE_PATH) |
GET | google_drive_integration_route.py:110 |
無 JWT;OAuth state+瀏覽器 nonce cookie 驗證 |
豁免 | 無 | 無 UI(Google 導回) | — | 外部導回端點,刻意不設使用者守門 |
/integrations/google-drive/verify-credentials |
POST | api/cloud_integration/routes/drive_app_credential_verify_route.py:32 |
J;service 層 PA+storage-config.read(app/cloud_integration/service/drive_app_credential_verify_service.py:74-78) |
隨 storage-config 新名的 read(見文末定案結論) | storage-config.read |
GoogleDriveAppConfigForm(/system/drive-app-config) |
tenant | 平台憑證設定頁,見 storage-config 段 |
/integrations/google-drive/sync-jobs |
GET | api/cloud_integration/routes/google_drive_sync_route.py:43 |
J+L+C(cloud_integration.read) | evidence.cloud-integration.read |
cloud_integration.read |
SyncJobHistoryDialog、GoogleDriveIntegrationCard |
tenant | |
/integrations/google-drive/sync-jobs/<uid>/retry |
POST | google_drive_sync_route.py:90 |
J+L+C(cloud_integration.update) | evidence.cloud-integration.update |
cloud_integration.update |
SyncJobHistoryDialog |
tenant | |
/integrations/google-drive/projects/<p>/init-folders |
POST | google_drive_sync_route.py:111 |
J+L;成員:manager(app/cloud_integration/service/drive_sync_admin_service.py:136) |
grc.project.update |
無 | ProjectCloudIntegrationsPanel |
org_unit | 專案 manager 觸發,非租戶管理員;見文末定案結論 |
/integrations/google-drive/projects/<p>/verify-and-repair-folders |
POST | google_drive_sync_route.py:143 |
J+L;成員:manager | grc.project.update |
無 | ProjectCloudIntegrationsPanel |
org_unit | 同上 |
/integrations/google-drive/projects/<p>/folders |
GET | google_drive_sync_route.py:177 |
J+L+C(cloud_integration.read) | evidence.cloud-integration.read |
cloud_integration.read |
ProjectCloudIntegrationsPanel、ProjectAuditorOverview |
org_unit | 專案頁用,要求租戶級 read——與上兩支的「專案 manager 即可」不一致,見文末定案結論 |
/integrations/google-drive/tenant/rebuild-all |
POST | google_drive_sync_route.py:209 |
J+L+C(cloud_integration.update) | evidence.cloud-integration.update |
cloud_integration.update |
GoogleDriveIntegrationCard |
tenant | 破壞性操作 |
/integrations/google-drive/webhook/register |
POST | google_drive_sync_route.py:239 |
J+L+C(cloud_integration.update) | evidence.cloud-integration.update |
cloud_integration.update |
GoogleDriveIntegrationCard |
tenant | |
/webhooks/google-drive/<tenant_id> |
POST | api/cloud_integration/routes/google_drive_webhook_route.py:39 |
無 JWT;X-Goog-Channel-ID+X-Goog-Channel-Token 比對 |
豁免 | 無 | 無 UI(Google 推送) | — | 確認刻意不設守門:Google 呼入、恆回 200;身分靠 channel token 比對 |
google_drive_integration_route.py 4 個、google_drive_sync_route.py 7 個、drive_app_credential_verify_route.py 1 個、google_drive_webhook_route.py 1 個。
cloud_integration.update 不是孤兒:有 3 支 route 守它(retry、rebuild-all、webhook register),FE GoogleDriveIntegrationCard.vue:219、SyncJobHistoryDialog.vue:18 也讀它,10 個角色持有。它沒出現在 /settings/cloud-integrations 選單綁定(該頁只綁 create/delete/read),所以「選單反查」會把它誤判成沒人用。
jedi-evidence-classification 所有 route 由動態子類套上宿主 jwt_required(core/plugins/evidence_classification.py:608),沒有授權照守門、沒有能力點(套件 CAPABILITIES 為空,jedi_evidence_classification/plugin/contract.py:25)。專案層檢查在 service:_require_participant/_require_manager(jedi_evidence_classification/app/service/evidence_batch_service.py:1472-1481),宿主實作為精確查 participant.role == "manager"(core/plugins/evidence_classification.py:72-114)。
| route 路徑 | HTTP | 程式位置 | 現有守門 | 新三段名 | 現有能力點 | 對應 UI | 範圍層 | 備註 |
|---|---|---|---|---|---|---|---|---|
/evidence-batches |
POST | jedi_evidence_classification/api/routes/evidence_batch_route.py:51 |
J;成員:manager(service :412) |
evidence.classification.create |
無 | AutoClassifyBatch |
org_unit | 建批次 |
/evidence-batches |
GET | evidence_batch_route.py:75 |
J;成員:參與者(:436,440) |
evidence.classification.read |
無 | AutoClassifyList |
org_unit | |
/evidence-batches/<b> |
GET | evidence_batch_route.py:101 |
J;成員:參與者(:462) |
evidence.classification.read |
無 | AutoClassifyBatch |
org_unit | |
/evidence-batches/<b> |
DELETE | evidence_batch_route.py:115 |
J;成員:manager(:732) |
evidence.classification.delete |
無 | AutoClassifyList |
org_unit | |
/evidence-batches/<b>/files |
POST | evidence_batch_route.py:122 |
J;成員:manager(:513) |
evidence.classification.update |
無 | AutoClassifyBatch |
org_unit | 上傳檔進批次 |
/evidence-batches/<b>/files/<f> |
DELETE | evidence_batch_route.py:137 |
J;成員:manager(:542) |
evidence.classification.update |
無 | AutoClassifyBatch |
org_unit | 從批次移出檔案 |
/evidence-batches/<b>/seal |
POST | evidence_batch_route.py:145 |
J;成員:manager(:552) |
evidence.classification.update |
無 | AutoClassifyBatch |
org_unit | 封存批次 |
/evidence-batches/<b>/classify |
POST | evidence_batch_route.py:153 |
J;成員:manager(:996) |
evidence.classification.update |
無 | AutoClassifyBatch |
org_unit | 送 AI 分類(花額度) |
/evidence-batches/<b>/archive |
POST | evidence_batch_route.py:176 |
J;成員:manager(:577) |
evidence.classification.update |
無 | AutoClassifyBatch |
org_unit | 把分類結果寫進任務佐證 |
/evidence-batches/<b>/purge |
POST | evidence_batch_route.py:183 |
J;成員:manager(:669) |
evidence.classification.delete |
無 | AutoClassifyBatch |
org_unit | 清掉暫存檔 |
/classification-run/<r>/state |
GET | evidence_batch_route.py:197 |
J;成員:參與者(:824) |
evidence.classification.read |
無 | useEvidenceClassification |
org_unit | |
/classification-run/<r>/state |
PUT | evidence_batch_route.py:202 |
J;成員:manager(:839) |
evidence.classification.update |
無 | 同上 | org_unit | 人工審閱結果 |
/classification-run/<r>/file/<f>/preview |
GET | evidence_batch_route.py:212 |
J;成員:參與者(:885) |
evidence.classification.read |
無 | EvidenceFilePreviewDialog |
org_unit | |
/classification-run/<r>/report/validation |
GET | evidence_batch_route.py:230 |
J;成員:參與者(:909) |
evidence.classification.read |
無 | useEvidenceClassification |
org_unit | |
/classification-run/<r>/report/adjudication |
GET | evidence_batch_route.py:236 |
J;成員:參與者(:920) |
evidence.classification.read |
無 | 同上 | org_unit | |
/classification-ground-truth |
POST | jedi_evidence_classification/api/routes/evidence_classification_route.py:19 |
J;任一專案的 manager(evidence_classification_service.py:58) |
evidence.classification.update |
無 | 無 UI(FE 無呼叫) | tenant | 評估用正解匯入,FE 沒有入口;見文末定案結論去留 |
/classification-profiles |
GET | jedi_evidence_classification/api/routes/classification_profile_route.py:51 |
J;service:storage-config.update(classification_profile_service.py:165,宿主 core/plugins/evidence_classification.py:137) |
evidence.classification.read |
storage-config.update |
AiServiceConfigForm(/system/ai-service-config) |
tenant | 讀也要 update——今天的設計 |
/classification-profiles |
POST | classification_profile_route.py:65 |
同上 | evidence.classification.create |
storage-config.update |
同上 | tenant | |
/classification-profiles/<p> |
PUT | classification_profile_route.py:72 |
同上 | evidence.classification.update |
storage-config.update |
同上 | tenant | |
/classification-profiles/<p> |
DELETE | classification_profile_route.py:77 |
同上 | evidence.classification.delete |
storage-config.update |
同上 | tenant | |
/classification/available-models |
GET | classification_profile_route.py:84 |
J;無其他檢查(service :120-126 只取身分) |
evidence.classification.read |
無 | AutoClassifyList、AutoClassifyBatch |
tenant | 輔助端點 |
evidence_batch_route.py 15 個、classification_profile_route.py 5 個、evidence_classification_route.py 1 個。
「分類設定」該不該跟批次同一資源:批次的寫入看專案成員角色、分類設定看租戶管理員,兩者授權對象不同。建議拆成 evidence.classification(批次與結果)與 evidence.classification-profile(AI 分類設定),列入見文末定案結論。主表暫填前者。
storage-config.* 四顆宣告在 jedi_file_upload/plugin/contract.py:33-37。route 不直接守它,而是三條路徑間接用:
jedi_system_core,T-1.4 範圍)依 GROUP 分流:STORAGE_CONFIG 與 AI_PROVIDER_CONFIG 兩組映到 storage-config.*(core/plugins/system_core.py:64,78)。| route 路徑 | HTTP | 程式位置 | 現有守門 | 新三段名 | 現有能力點 | 對應 UI | 範圍層 | 備註 |
|---|---|---|---|---|---|---|---|---|
/system/config/storage/restore-default |
GET | api/system_config/routes/system_config_route.py:119 |
J;assert_config_capability("STORAGE_CONFIG","read") |
<storage-config>.read |
storage-config.read |
StorageConfigForm(/system/storage-config) |
tenant | 只回出廠快照有無 |
/system/config/storage/restore-default |
POST | system_config_route.py:127 |
J;assert_config_capability("STORAGE_CONFIG","update") |
<storage-config>.update |
storage-config.update |
同上 | tenant | 恢復內建儲存 |
/system/config/ai-provider/model-options |
GET | system_config_route.py:100 |
J;assert_config_capability("AI_PROVIDER_CONFIG","read") |
見文末定案結論(AI 服務設定歸屬) | storage-config.read |
AiServiceConfigForm |
tenant | AI 服務設定頁借用 storage-config |
jedi-file-upload 的檔案端點(不開能力點,歸屬由檔案登記表決定):
| route 路徑 | HTTP | 程式位置 | 現有守門 | 新三段名 | 現有能力點 | 對應 UI | 範圍層 | 備註 |
|---|---|---|---|---|---|---|---|---|
/file/upload |
POST | jedi_file_upload/api/routes/upload_file_route.py:88 |
J | 不開能力點 | 無 | 全站上傳元件 | — | 上傳本身不判功能權;檔案掛到哪個功能時由該功能守 |
/file/upload/<uid> |
DELETE | upload_file_route.py:113 |
J+檔案歸屬(寫) | 不開能力點 | 無 | 同上 | — | 歸屬判斷委派各功能(core/plugins/_file_ownership.py、core/plugins/file_upload.py) |
/file/uploads |
POST | upload_file_route.py:124 |
J | 不開能力點 | 無 | 同上 | — | 批次上傳 |
/file/access-token/<uid> |
GET | upload_file_route.py:153 |
J+檔案歸屬(讀) | 不開能力點 | 無 | 全站下載/預覽 | — | 換短期下載憑證 |
/file/download/<uid> |
GET | upload_file_route.py:165 |
短期憑證或 JWT+檔案歸屬(讀) | 不開能力點 | 無 | 同上 | — | 瀏覽器導頁 |
/file/pdf-preview/<uid> |
GET | upload_file_route.py:200 |
同上 | 不開能力點 | 無 | 同上 | — |
檔案端點不開能力點的理由:一個檔案屬於哪個功能是登記表查出來的,同一支端點服務十幾種檔案,掛任何單一能力點都會讓其他功能的檔案打不開。權限已由「該檔案所屬功能的原本守門」代判。
jedi-survey 的守門 decorator 是宿主注入的 port(jedi_survey/api/guards.py);授權照 require_license("survey") 全端點都有,能力點名預設在 jedi_survey/plugin/contract.py:32-35,89-91。讀取端點全部沒有 survey.read,只有授權照。
| route 路徑 | HTTP | 程式位置 | 現有守門 | 新三段名 | 現有能力點 | 對應 UI | 範圍層 | 備註 |
|---|---|---|---|---|---|---|---|---|
/survey-folders/menu |
GET | jedi_survey/api/routes/survey_folder_route.py:33 |
J+L(survey) | survey.survey.read |
無 | survey-v2(/survey/manage) |
org_unit | 輔助端點 |
/survey-folders |
POST | survey_folder_route.py:45 |
J+L | survey.survey.read |
無 | 同上 | org_unit | 列表 |
/survey-folder/<uid> |
GET | survey_folder_route.py:60 |
J+L | survey.survey.read |
無 | 同上 | org_unit | |
/survey-folder |
POST | survey_folder_route.py:73 |
J+L+C(survey.create) | survey.survey.create |
survey.create |
同上 | org_unit | 資料夾不另開資源 |
/survey-folder/<uid> |
PUT | survey_folder_route.py:90 |
J+L+C(survey.update) | survey.survey.update |
survey.update |
同上 | org_unit | |
/survey-folder/<uid> |
DELETE | survey_folder_route.py:109 |
J+L+C(survey.delete) | survey.survey.delete |
survey.delete |
同上 | org_unit | |
/surveys/menu |
GET | jedi_survey/api/routes/survey_route.py:34 |
J+L | survey.survey.read |
無 | SurveyPickerDialog(任務設置挑問卷) |
org_unit | 輔助端點 |
/surveys |
POST | survey_route.py:59 |
J+L | survey.survey.read |
無 | survey-v2 |
org_unit | 列表 |
/survey/<uid> |
GET | survey_route.py:88 |
J+L | survey.survey.read |
無 | survey-v2、SurveyPreview、AuditControlRef、RoundAuditReviewView、RoundPoamView |
org_unit | 稽核頁也讀問卷本體 |
/survey |
POST | survey_route.py:105 |
J+L+C(create) | survey.survey.create |
survey.create |
survey-v2 |
org_unit | |
/survey/<uid> |
PUT | survey_route.py:133 |
J+L+C(update) | survey.survey.update |
survey.update |
同上 | org_unit | |
/survey/<uid> |
DELETE | survey_route.py:156 |
J+L+C(delete) | survey.survey.delete |
survey.delete |
同上 | org_unit | |
/survey/excel-import |
POST | survey_route.py:175 |
J+L+C(create) | survey.survey.import |
survey.create |
BatchImportDialog |
org_unit | 匯入類獨立動詞 |
/survey/import-template/token |
GET | survey_route.py:201 |
J+L | survey.survey.import |
無 | signedDownloadUtil |
org_unit | 換範本下載憑證 |
/survey/import-template |
GET | survey_route.py:209 |
短期憑證(signed_token_required) |
豁免(憑證端點) | 無 | 同上 | — | 憑證由上一支發 |
/survey/move |
POST | survey_route.py:221 |
J+L+C(create) | survey.survey.update |
survey.create |
survey-v2 |
org_unit | 移資料夾是改屬性,今天守 create |
/survey/<uid>/clone |
POST | survey_route.py:242 |
J+L+C(create) | survey.survey.create |
survey.create |
同上 | org_unit | |
/survey/<uid>/release |
PUT | survey_route.py:265 |
J+L+C(update) | survey.survey.publish |
survey.update |
同上 | org_unit | 發布=狀態轉換獨立動詞 |
/survey/<uid>/release |
DELETE | survey_route.py:279 |
J+L+C(delete) | survey.survey.publish |
survey.delete |
同上 | org_unit | 取消發布;今天守 delete |
/survey-question |
POST | jedi_survey/api/routes/survey_question_route.py:33 |
J+L+C(create) | survey.survey.update |
survey.create |
survey-v2 |
org_unit | 題目、頁面是問卷內容,改它們=改問卷 |
/survey-question/<uid> |
PUT | survey_question_route.py:62 |
J+L+C(update) | survey.survey.update |
survey.update |
同上 | org_unit | |
/survey-question/<uid> |
DELETE | survey_question_route.py:98 |
J+L+C(delete) | survey.survey.update |
survey.delete |
同上 | org_unit | |
/survey-questions/reorder |
POST | survey_question_route.py:113 |
J+L+C(create) | survey.survey.update |
survey.create |
同上 | org_unit | |
/survey-question/move |
POST | survey_question_route.py:134 |
J+L+C(create) | survey.survey.update |
survey.create |
同上 | org_unit | |
/survey-page |
POST | jedi_survey/api/routes/survey_page_route.py:33 |
J+L+C(create) | survey.survey.update |
survey.create |
同上 | org_unit | |
/survey-page/<uid> |
PUT | survey_page_route.py:61 |
J+L+C(update) | survey.survey.update |
survey.update |
同上 | org_unit | |
/survey-page/<uid> |
DELETE | survey_page_route.py:88 |
J+L+C(delete) | survey.survey.update |
survey.delete |
同上 | org_unit | |
/survey-pages/reorder |
POST | survey_page_route.py:102 |
J+L+C(create) | survey.survey.update |
survey.create |
同上 | org_unit | |
/survey-page/move |
POST | survey_page_route.py:123 |
J+L+C(create) | survey.survey.update |
survey.create |
同上 | org_unit |
題目與頁面的增刪歸問卷 update 是依「其他動作歸 update」規則:使用者在問卷編輯器裡加一題,語意是「編輯這份問卷」,不是「建立一個題目資源」。今天的守法(加題守 create、刪題守 delete)讓「能改問卷但不能刪問卷」的角色連題目都刪不掉,改名時順手校正。
填答端(mount_answer_routes,jedi_survey/api/routing.py:73-109)全部 J+L(survey),沒有能力點。專案層檢查在 service:assert_task_survey_reader(專案參與者)、assert_task_survey_writer(被指派人本人或專案 manager)、assert_task_survey_manager(專案 manager),定義在 jedi_survey/app/common/task_survey_guard.py。
| route 路徑 | HTTP | 程式位置 | 現有守門 | 新三段名 | 現有能力點 | 對應 UI | 範圍層 | 備註 |
|---|---|---|---|---|---|---|---|---|
/task-surveys |
POST | jedi_survey/api/routes/task_survey_route.py:28 |
J+L;成員:參與者(task_survey_service.py:79) |
grc.job.read|grc.job-evidence.read(後者限已完成問卷) |
無 | JobExecutionDrawer |
org_unit | 列表(必帶 task) |
/task-survey/<uid> |
GET | task_survey_route.py:40 |
J+L;成員:參與者(:94) |
grc.job.read|grc.job-evidence.read(後者限已完成問卷) |
無 | SurveyPreview |
org_unit | |
/task-survey/<uid> |
PUT | task_survey_route.py:49 |
J+L;成員:manager(:112) |
grc.job.update |
無 | JobExecutionDrawer |
org_unit | 管理者改任務問卷狀態(含審核轉換);見文末定案結論 |
/task-survey/configured/<uid> |
PUT | task_survey_route.py:155 |
J+L;成員:manager(:613) |
grc.job.update |
無 | JobExecutionDrawer |
org_unit | 設定任務要用哪份問卷、要不要審核;屬任務設置 |
/task-survey/import-template/<task_uid> |
GET | task_survey_route.py:65 |
J+L;無成員檢查 | grc.job.read |
無 | SurveyPreview |
org_unit | 守門缺口:service generate_task_survey_question_import_excel_template_data(task_survey_service.py:206)不驗身分,見缺口清單 |
/task-survey/import-answers |
POST | task_survey_route.py:134 |
J+L;成員:manager(:296) |
grc.job.update |
無 | SurveyPreview |
org_unit | Excel 批次匯入答案;填答端一律歸 grc.job.update,不開 import |
/project-survey/answers/<uid> |
GET | jedi_survey/api/routes/question_answer_route.py:30 |
J+L;成員:參與者(question_answer_service.py:102) |
grc.job.read|grc.job-evidence.read(後者限已完成問卷) |
無 | SurveyPreview |
org_unit | |
/project-survey/answers/<uid> |
PUT | question_answer_route.py:40 |
J+L;成員:被指派人或 manager(:120) |
grc.job.update |
無 | 同上 | org_unit | |
/project-survey/answers/<uid>/patch |
POST | question_answer_route.py:59 |
同上(:255) |
grc.job.update |
無 | 同上 | org_unit | |
/project-survey/answers/<uid>/checkpoint |
POST | question_answer_route.py:89 |
同上(:407) |
grc.job.update |
無 | 同上 | org_unit | 暫存/提交 |
/project-survey/histories/menu/<uid> |
GET | jedi_survey/api/routes/question_answer_history_route.py:24 |
J+L;成員:參與者(question_answer_history_service.py:58) |
grc.job.read|grc.job-evidence.read(後者限已完成問卷) |
無 | SurveyPreview |
org_unit | 輔助端點 |
/project-survey/histories |
POST | question_answer_history_route.py:35 |
同上(:71) |
grc.job.read|grc.job-evidence.read(後者限已完成問卷) |
無 | 同上 | org_unit | |
/project-survey/history/revert |
POST | question_answer_history_route.py:47 |
J+L;成員:被指派人或 manager(:82) |
grc.job.update |
無 | 同上 | org_unit | |
/project-survey/history-details |
POST | jedi_survey/api/routes/question_answer_history_detail_route.py:20 |
J+L;成員:參與者(question_answer_history_detail_service.py:35) |
grc.job.read|grc.job-evidence.read(後者限已完成問卷) |
無 | 同上 | org_unit | |
/survey-discussions |
POST | jedi_survey/api/routes/survey_discussion_route.py:25 |
J+L;成員:參與者(survey_discussion_service.py:47) |
grc.job.read|grc.job-evidence.read(後者限已完成問卷) |
無 | SurveyPreview |
org_unit | 列表 |
/survey-discussion |
POST | survey_discussion_route.py:43 |
J+L;無成員檢查 | grc.job.update |
無 | 同上 | org_unit | 守門缺口:service add_discussion(survey_discussion_service.py:69)不驗身分,見缺口清單 |
/survey-discussion/<uid> |
PUT | survey_discussion_route.py:65 |
J+L+C(survey.update);作者本人(jedi_survey/app/service/survey_discussion.py:54) |
grc.job.update |
survey.update |
同上 | org_unit | 改自己的留言卻要問卷設計權 |
/survey-discussion/<uid> |
DELETE | survey_discussion_route.py:85 |
J+L+C(survey.delete);作者本人(:66) |
grc.job.update |
survey.delete |
同上 | org_unit | 同上 |
討論串放在填答這一組:它掛在任務問卷(ref_id=task_survey_uid)上,是受訪者與審核者的對話,不是問卷設計。今天改/刪留言要 survey.update/delete,等於只會填問卷的人留了言就改不掉。
| 舊名 | 主表有 route 守它? | 新名 | 其他引用處 |
|---|---|---|---|
device.create |
有:建立、匯入三支 | asset.device.create/.import |
套件 jedi_asset/plugin/contract.py;綁 /device/device-manage;FE DeviceManage.vue:69 |
device.read |
有:列表、明細、選單、引用數、匯出 | asset.device.read/.export |
角色範本 core/role_templates.py:14;app/module_frame/service/template_lookup_scope.py:16;di_containers/dashboard_apis/device.py:19;FE DeviceManage.vue:70 |
device.update |
有:PUT | asset.device.update |
FE DeviceImportDialog.vue:34(判斷匯入按鈕,與 BE 守 create 不一致) |
device.delete |
有:DELETE | asset.device.delete |
FE DeviceManage.vue:68 |
remote-agent-manage.create |
有:15 個管理 method 全守它 | detection.remote-agent.*(依主表拆) |
core/plugins/remote_agent.py:167 |
remote-agent-manage.read/update/delete |
無 | detection.remote-agent.read/update/delete |
只綁 /system/remote-agent-manage 選單;11 個角色持有 |
plugin.update |
有:工具設定建立、修改、重置、測試連線 | detection.plugin.create/update |
套件 jedi_detection/plugin/contract.py:48 |
plugin.create/read/delete |
無 | detection.plugin.create/read/delete |
只綁 /plugin/tool-plugin-manage 選單;10 個角色持有 |
detection-profile.create/read/update/delete |
有:基準 18 支 | detection.profile.* |
套件 contract :49-52;角色範本 :16(read);core/plugins/_file_ownership.py:224-225;FE DetectionProfileManageView.vue:69-71、ProfileVersionTable.vue:227-228 |
scan-zone.read |
有:GET | detection.scan-zone.read |
套件 contract :53;FE config/scanZone.js |
scan-zone.update |
有:新增、修改、刪除、建議 | detection.scan-zone.create/update/delete |
套件 contract :54;FE config/scanZone.js |
cloud_integration.create |
有:auth-url | evidence.cloud-integration.create |
core/host_capabilities.py:38;FE GoogleDriveIntegrationCard.vue:218 |
cloud_integration.read |
有:sync-jobs、專案資料夾 | evidence.cloud-integration.read |
core/host_capabilities.py:40;FE 同檔 :222 |
cloud_integration.update |
有:retry、rebuild-all、webhook register | evidence.cloud-integration.update |
core/host_capabilities.py:41;FE 同檔 :219、SyncJobHistoryDialog.vue:18;不在選單綁定(見雲端整合段) |
cloud_integration.delete |
有:中斷連線 | evidence.cloud-integration.delete |
core/host_capabilities.py:39;FE 同檔 :220 |
storage-config.read |
有:restore-default GET、model-options、Drive 憑證驗證(service) | 見文末定案結論 | jedi_file_upload/plugin/contract.py:35;泛用設定 GROUP 分流 core/plugins/system_core.py:64,78;綁 /system/storage-config、/system/drive-app-config、/system/ai-service-config、/system/support |
storage-config.update |
有:restore-default POST;AI 分類設定 4 支(service) | 見文末定案結論 | core/plugins/evidence_classification.py:137;同上四頁選單 |
storage-config.create/delete |
只經泛用設定端點(T-1.4 範圍) | 見文末定案結論 | 只綁 /system/storage-config;11 個角色持有 |
survey.create |
有:建問卷、資料夾、匯入、搬移、複製、題目與頁面的新增/排序/搬移 | survey.survey.create/update/import |
套件 contract :32;common/authz/license.py:44(範例註解) |
survey.read |
無 | survey.survey.read |
綁 /survey/manage;角色範本 :48;di_containers/dashboard_apis/survey.py:30,44;12 個角色持有 |
survey.update |
有:改問卷、資料夾、題目、頁面、發布、改留言 | survey.survey.update/publish、grc.job.update |
套件 contract :34 |
survey.delete |
有:刪問卷、資料夾、題目、頁面、取消發布、刪留言 | survey.survey.delete/update/publish、grc.job.update |
套件 contract :35 |
remote-agent-manage.read/update/delete(3)、plugin.create/read/delete(3)、survey.read(1),共 7 個。全都綁在選單上、角色也持有,孤兒不等於沒用:今天它們決定「看不看得到那一頁」,改名後由主表對應 route 掛上。storage-config.create/delete 只被泛用設定端點(T-1.4)間接守,不算孤兒。
卡片提到的孤兒 cloud_integration.update:不是孤兒,3 支 route 守它,只是沒綁選單。
加值包(license_module) |
內含舊 resource_type | 新資源 | 落在模組 | 整包同一模組? |
|---|---|---|---|---|
| 檢測工具包 | remote-agent-manage、detection-profile、plugin |
detection.remote-agent、detection.profile、detection.plugin |
detection | ✓ |
| 雲端整合包 | cloud_integration |
evidence.cloud-integration |
evidence | ✓ |
| 問卷包 | survey |
survey.survey |
survey | ✓ |
| 基礎設施豁免 | scan-zone |
detection.scan-zone |
detection | 不在照上;歸 detection 不影響授權判定 |
| 基礎包 | device |
asset.device |
asset | 與 asset.information-system(T-1.1)同模組 ✓ |
| 基礎包 | storage-config |
見文末定案結論 | evidence 或 system | 不是加值包,歸哪都不違反硬規則 |
| (無照鍵) | 證據分類(今天無 resource_type) | evidence.classification |
evidence | 見文末定案結論:新資源的 license_module 填什麼(見文末定案結論) |
注意兩處會讓加值包「看起來」跨界:
grc.job 的任務操作就有一部分在 detection 模組下,客戶買檢測包後還要另外勾 detection 才能在任務頁跑掃描。建議歸 grc.job,授權照守門 L(plugin) 照留——授權照與能力點是兩層,任務端點受檢測包管制不需要它的能力點也在 detection。grc.job.read/update;授權照 L(survey) 照留,問卷包的能力點仍整包在 survey(survey.survey)。建議歸 system,名字 system.storage-config.*;同時把借用它的兩頁拆出去。
core/plugins/evidence_classification.py:126-129、common/constant/ai_service_config.py:11)。FR-132 本來就要整批改名與補 seed,正是拆開的時機:
ai-quota 一起裁(同屬「AI 怎麼用」)。/system/support → 交 T-1.4 確認它實際讀什麼,再決定。evidence.storage-config,主表只換前綴。D12 候選表本卡相關四張:public.devices、compliance.evidence_batches、compliance.detection_executions、survey.surveys。DEV 實查各表都開 RLS;下表看「有 API 直接列子表」時,子表的 RLS 是否也跟著父表收緊。
| 父表 | 子表 | 子表 RLS 形狀(DEV) | 有 API 直接讀子表嗎 | 觀察 |
|---|---|---|---|---|
public.devices(有 org_unit_id) |
無直接子表 | — | — | 單表,加部門隔離只動它 |
compliance.evidence_batches(有 org_unit_id) |
evidence_batch_files、evidence_classification_runs |
各自獨立用 tenant_id 判,不透過父表(三表 policy 都是 app_tenant_allowed_for_session(tenant_id)) |
有:/evidence-batches/<b>/files(寫)、/classification-run/<r>/*(以 run uid 定址,5 支) |
會繞過:父表加部門隔離後,拿得到 run uid 的人仍能從 /classification-run/<r>/state、/file/<f>/preview 讀到子表內容。service 層有專案成員檢查擋著,但 RLS 層要補——子表要嘛自己加 org_unit_id 條件(兩張子表都有 org_unit_id 欄),要嘛改成 EXISTS (父表) |
compliance.detection_executions(有 org_unit_id) |
detection_execution_groups(父子關係反過來:群組是上層) |
兩表各自 tenant_id 判 |
有:/detection-tools/execution-groups/<g>/*(5 支)以群組 uid 定址 |
同上,群組表也要一起加;兩表都有 org_unit_id |
survey.surveys(有 org_unit_id) |
survey_pages、survey_questions、survey_discussions、question_answers |
透過父表 EXISTS(pages → surveys、questions → pages、discussions → surveys、answers → questions → pages) |
有:題目、頁面、討論、答案端點都直接以子表 uid 定址 | 不會繞過:子表 policy 鏈到 surveys,父表加條件自動傳下去 |
| 同上 | task_surveys、question_answer_histories |
task_surveys 鏈到 compliance.workflow_executions(不是 surveys) |
有:/task-survey/*、/project-survey/* |
任務問卷跟著專案隔離,不跟著問卷本體。若 D12 要「看不到別部門的問卷」,這條線不受影響是對的(受訪者要能填別部門出的問卷);若要「看不到別部門的填答」,要動的是 workflow_executions 那條 |
決策者 2026-10-06 逐條裁決。
grc.job;開始、取消、重跑歸 update,不算 assign。授權照 L(plugin) 照留。survey.response。 填答端 API 歸 grc.job.read/update,授權照 L(survey) 照留;兩支守錯的(改、刪自己留言要求問卷設計權)改 grc.job.update。survey.survey 只剩問卷設計那組。理由:填問卷的人是任務指派人、在任務頁填,身分由任務決定;授權照與能力點是兩層,硬規則管的是能力點模組,填答不需要自己的能力點,故不違反。grc.job.update。update,不開 approve。core/plugins/remote_agent.py 塞兩顆(讀 detection.remote-agent.read、寫對應動詞);落點 T-2.1 順帶,套件發版等令。決策者裁示:FR-132 屬整體大改,jedi-* 該動就動、不逐條問。evidence.classification(批次與結果)與 evidence.classification-profile(分類設定);license_module 填 evidence-classification,視為基礎包。system.storage-config.*;AI 服務設定+AI 分類設定 → ai.ai-provider-config.*;Drive 應用程式憑證 → platform 層;支援頁 → platform.support.*(已隨 T-1.4/T-1.5 裁)。grc.project(folders 歸 read、init/repair 歸 update),L(cloud_integration) 照留。GET /integrations/google-drive 掛 evidence.cloud-integration.read,出貨範本一般成員組要帶這顆。/classification-ground-truth 保留,掛 evidence.classification.update(灌人工標註答案給準確率報表用,原廠/顧問導入時用;runbook docs/api/evidence-classification/ground-truth-operations.md)。survey.survey.update。survey.survey.publish。另:設備「選單」類端點(/devices/menu 等被專案/SSP 頁拿來挑選的)新名是「跟呼叫頁面的權限」,不是 asset.device.read(design 通則 B)。
本卡只讀,修正由首腦另開卡。
GET /task-survey/import-template/<task_uid> 不驗身分:service generate_task_survey_question_import_excel_template_data(jedi_survey/app/service/task_survey_service.py:206)直接以 task uid 查任務問卷產 Excel,知道 task uid 的登入者(同租戶,RLS 只擋跨租戶)就能拿到題目內容。比照同檔其他讀取端點補 assert_task_survey_reader。POST /survey-discussion 不驗身分:service add_discussion(jedi_survey/app/service/survey_discussion_service.py:69)沒有呼叫任何守門,同租戶任何登入者可在任一任務問卷留言。比照同檔 get_survey_discussions(:47)補 assert_task_survey_reader。GET /classification/available-models 只驗身分:回本租戶有哪些 AI 供應商已設金鑰;定案掛 ai.ai-provider-config.read。evidence.classification 未來要收進某加值包,宿主要先補 L(x),否則買不買都能用。jedi_asset/plugin/contract.py:77-80(device)、jedi_detection/plugin/contract.py:32-54(plugin、detection-profile、scan-zone)、jedi_survey/plugin/contract.py:32-35,89-91、jedi_file_upload/plugin/contract.py:33-37(storage-config)core/plugins/remote_agent.py:167、core/plugins/evidence_classification.py:137、core/host_capabilities.py:38-41、app/cloud_integration/service/drive_app_credential_verify_service.py:46、app/module_frame/service/template_lookup_scope.py:16、core/plugins/_file_ownership.py:224-225、core/plugins/system_core.py:64,78(GROUP 分流表)api/cloud_integration/routes/google_drive_integration_route.py:69,88、google_drive_sync_route.py:41,88,175,207,237core/role_templates.py:14,16,48di_containers/dashboard_apis/device.py:19、survey.py:30,44route_capabilities:/device/device-manage、/plugin/detection-profile-manage、/plugin/tool-plugin-manage、/settings/cloud-integrations、/survey/manage、/system/remote-agent-manage、/system/scan-zone、/system/storage-config、/system/drive-app-config、/system/ai-service-config、/system/supportviews/device/DeviceManage.vue:68-70、DeviceImportDialog.vue:34、config/scanZone.js、views/detection-profile/DetectionProfileManageView.vue:69-71、components/ProfileVersionTable.vue:227-228、components/integrations/GoogleDriveIntegrationCard.vue:218-222、SyncJobHistoryDialog.vue:18沿革見 FR-132-LOG.md 與 git log。