本卡為 FR-086 母案。掃 jedi-file-upload 套件(68 檔)+主專案宿主接線(10 檔),切三棒。只掃不修。 子卡清單在末段。
產品裡所有「上傳檔案、下載檔案、預覽檔案」都經過這支套件:使用者傳上來的檔案存到哪(主機硬碟/物件儲存/客戶自己的設備)、存成什麼檔名、下載時怎麼判斷「這個檔是不是你的」。這個 arc 要回答:有沒有辦法把檔案寫到不該寫的地方、有沒有辦法下載到別人的檔案、憑證會不會外洩。
api/routes/upload_file_route.py:101,os.path.join(payload.get('upload_type'), payload.get('uid')))——那兩個值來自請求內容,沒看到 ../ 過濾。若成立就是「檔案可以寫到指定目錄外面」。api/routes/upload_file_route.py:150-156,/file/access-token/<uid> 只掛 @auth_required,拿到 uid 就簽發)——中間沒有「這個檔是不是你的」這道檢查。infra/repository/upload_file_repo_impl.py:41-45,get_by_uid 只 filter_by(uid=...)),加上那張表沒有租戶欄位——猜到或列舉到編號就取得檔案。common/utils/file_utils.py:16,filename.split('.')[-1] 取副檔名)——沒有副檔名白名單、沒有檔名正規化、沒有單檔大小檢查。app/upload_file/service/managed_file_upload_service.py:99-119,secure=v.get('secure', False))。api/+app/+ports/+common/+plugin.py。上傳、下載、預覽、發憑證四條對外路徑都在這,三個最直接的疑點也都在這。app/upload_file/+infra/upload_file/+core/upload_file_wiring.py+di_containers/upload_file/。檔數少但密度最高:決定「用哪個儲存後端、拿誰的憑證、算不算你的檔」全在這半邊(比照 FR-079 B2、FR-081 I2 的形狀)。infra/+domain/+migrations/。三個後端(主機硬碟/MinIO/SeaweedFS)的實際讀寫、檔案編號查詢、以及那張沒有租戶欄位的表。建議順序 B1 → B2 → B1b(依疑點密度)。一次只派一棒,每棒獨立驗收完才派下一棒(FR-081 起的紀律)。
🔴 原本規劃的第四棒「remote_agent 檔案通道」已砍掉——首腦查證它與 FR-077 的 CM-1594(R3 宿主接線,17 檔)範圍完全重疊(api/remote_agent//app/remote_agent//infra/remote_agent//remote_agent_adapter.py 都在那張卡裡)。要掃那條路請派 CM-1594,不要在本 arc 重開。