本卡為 FR-083 母案。掃 jedi-ai-dashboard(套件 34 檔 + BE 宿主接線 18 檔)。只掃不修,修正卡另開、由 PM 統一安排。建議 D2(宿主)先跑——理由見下。

這在做什麼(白話)

系統裡有一個「AI 儀表板」:使用者用自然語言問問題(例如「列出所有專案的進度」),AI 會自己決定要呼叫系統裡的哪一支查詢功能,把查到的資料拿去設計版面,做成圖表顯示。

這一棒要回答的是:AI 能呼叫的那些查詢功能,有沒有做權限檢查?查到的資料會不會被送到公司外面?使用者能不能用自然語言誘導 AI 去查他本來看不到的東西?

🔴 為什麼這支是目前為止風險最高的(三個理由)

① FR-079 已經證明這條路有洞,但我們只驗證了 27 支裡的 1 支。

FR-079 的 F13 查到「AI 儀表板可以直接呼叫公告查詢,不經過網頁那層的任何權限檢查,而且部門過濾永遠失效(呼叫端寫死 params={})」。當時只追了公告那一支。

這次盤點發現:di_containers/dashboard_apis/ 底下有 14 支申報檔,合計申報了 27 支 API——

participant(專案成員)  7 支   ← 「你在這個專案能幹嘛」的資料源
auth(認證)            4 支   ← get_users / get_tenants / get_roles / get_org_units
flow_engine             3 支
oscal / project / survey 各 2 支
bulletin / feedback / device / system_menu /
system_config / module_frame / user_auth_provider  各 1 支
                       ────
                        27 支

auth.get_usersauth.get_tenantsauth.get_org_units 全部在這條旁路上——那是全站使用者名冊、租戶清單、組織架構。還有 26 支從未驗證過。

② 查到的資料會原文送給第三方 LLM。 F13 已確認「結果前三筆原文送第三方」。27 支 API 的回傳內容都可能經這條路出去。

③ 使用者的自然語言會決定 AI 呼叫哪支 API。 domain/service/dashboard_generation_domain_service.py(329 行,套件最大檔)與 app/service/ai_dashboard_app_service.py(258 行)負責「AI 選哪支 API、怎麼組版面」——提示詞注入的天然位置:能不能用文字誘導 AI 去選一支本來不該給這個使用者的 API?

🔴 為什麼切兩棒(與 FR-082 的判斷不同)

依 FR-079 換來的判準先查「這支有沒有宿主那一半」——有,而且宿主那半邊是主角不是配角

套件本體    jedi_ai_dashboard/ + harness/     34 檔  2,296 行
BE 宿主接線  api/ai_dashboard/                 105 行
            di_containers/ai_dashboard/       153 行
            di_containers/dashboard_apis/     14 支申報檔、27 支 API
            ------------------------------------------------
                                              18 檔  約 800 行

兩邊都夠大、且 scanRoot 只能指一個目錄,所以必須分開。 這與 FR-082(jedi-ai-bot 宿主僅 3 檔 89 行,併進卡片背景即可)不同。

怎麼拆

為什麼 D2 先跑:F13 已經證明那半邊有洞,而 27 支 API 的權限形狀是本 arc 的核心問題。D1 跑第二棒時可以帶著 D2 的結論去看「AI 的選擇邏輯會不會放大那些洞」。兩棒的發現要放在一起對(FR-078 N1/N2、FR-081 I1/I2 的經驗)。