本卡屬 FR-188(母卡 CM-3728),修 FR-187 資安掃描發現的 #252(中)、#253(低)、#255(中)。嚴重度:中×2+低×1。發現原文、檔名行號、面板票數在
docs/features/FR-187-2611-post-fr172-security-scan/reports/(工作坊工作區compliance-manager-be/.worktrees/CM-3711/裡,主線還沒合;總表docs/features/security-scan-consolidated/README.md§3.1 同樣在那裡)。Stage 未排,由排批的人決定(見下方「排批注意」)。
落地版是一台主機裝在客戶那裡,程式當初假設「一台機器只有一家公司」。客戶可以開子公司(多租戶)之後,這個假設不成立了:子公司的系統管理員角色出廠就是 *.*.*,所以自動拿到更新中心與支援頁的能力點,而這兩處在落地版只看能力點、不看是不是總部。
結果:子公司管理員能①從更新中心產生並下載整台機器的診斷包與升級紀錄(#252),②讓整台機器立即升級、排程升級、關掉每日自動檢查(#253),③從支援頁下載整機診斷包,拿到總部與其他子公司的應用日誌與錯誤事件(#255)。診斷包是主機以系統身分收集、讀伺服器上的 app.log,不受資料庫 RLS(每個客戶只能看自己資料的隔離機制)管。
/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/app/product_update/service/product_update_app_service.py:104-107 _assert_may_write:落地版直接放行
/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/app/product_update/service/product_update_app_service.py:182-230 寫入方法、request_diag、diag_file、upgrade_log_file 都只靠上面那道
/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/api/product_update/routes/product_update_route.py:200-210 ProductUpdateUpgradeLogRoute 只掛 read 能力點
/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/common/authz/log_viewer.py:32-37 require_log_viewer:落地版只看能力點
/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/app/support/service/diag_bundle_export_service.py:75 支援頁產整機診斷包
/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/common/authz/tenant_hq.py:55 require_tenant_hq()——「誰算總部」的唯一判斷(reuse)
行號以 2026-11-09 主線為準,對不上就以內容為準。
require_tenant_hq()(common/authz/tenant_hq.py:55),不要自己判 parent_id is None(.claude/rules/security/endpoints.md「全站共用設定的寫入過 require_tenant_hq()」)。_assert_may_write:落地版改呼叫 require_tenant_hq()、SaaS 維持 require_platform_admin()。upgrade_log_file、diag_file、request_diag 都經這支,一處改完三處生效;_can_write(:109-118)同時接 ForbiddenError,畫面按鈕會一起藏起來。diag_bundle_export_service.export 開頭落地版加 require_tenant_hq()。不要改 require_log_viewer 本身——系統日誌查詢頁走 RLS 分租戶,子公司看自己的日誌是對的,加在 require_log_viewer 會連查詢頁一起擋掉。job_id 能不能讓子公司組出升級紀錄網址(擋在 upgrade_log_file 就夠,確認即可)。common/authz/log_viewer.py 檔頭、product_update_app_service.py:105)。common/authz/ 屬核心共用邏輯):落地版子公司身分呼叫 _assert_may_write、diag_bundle_export_service.export 要 403;總部身分照過;SaaS 平台管理員照過。突變測試:把 require_tenant_hq() 那行拿掉,測試要紅。DEPLOYMENT_MODE=host,總部 Billows Tech 102)。開一個子公司、建一個子公司管理員帳號登入:更新中心按「產生診斷包」「下載升級紀錄」「立即更新」「關閉自動檢查」都回 403、按鈕不出現;支援頁「下載除錯包」回 403;「系統日誌查詢」照常看得到自己子公司的列。