# FR-039 分散式檔案 Agent — 進度表

> 最後更新：2026-06-18 · branch `feature/FR-039-evidence-agent`（BE + evidence-agent 同名）· **均未 push**
> 接手必讀順序：① `design.md`（需求/設計）→ ② 本進度表 → ③ `2026-06-18-FR039-handoff.md`（交接）→ ④ `2026-06-18-FR039-next-prompt.md`（prompt）

## 一句話

把證據檔案儲存拉出成「客戶端 evidence-agent」（每客戶一台、自帶 MinIO/Local + 本地 Postgres），雲端依 per-tenant 設定把檔案轉發過去，binary 不落雲端；SHA-256 防竄改；agent 端點集中在 registry 表、per-tenant 挑選。

## 階段進度

| 階段 | 內容 | 狀態 | Commit |
|------|------|------|--------|
| Phase 0 | de-risk spike（jedi-common `@transaction` 無 Redis/JWT 裸跑）| ✅ | — |
| Phase 1 | `evidence-agent` 服務（local/minio/docker/預覽/持久化 smoke 全通）| ✅ | evidence-agent `347671c` |
| Phase 2 | 雲端 `RemoteAgentAdapter` + service/route wiring（e2e 對真實 agent 全通）| ✅ | BE `1fb88622` |
| Phase 3 | SHA-256 防竄改（上傳算錨點、下載重算、竄改擋下 + 稽核）| ✅（要 mapper live 才生效，見下）| BE `1fb88622` |
| Registry（方案 B 後端）| `compliance.file_agents` 表 + `agent_uid` 解析（無 UI，直接 INSERT）| ✅ | BE `fa5f3fec` |
| 部署資產 | `evidence-agent/deploy/`（客戶 server 用 image 模式 compose）| ✅ | evidence-agent `1e1fd1a` |
| **Phase 4** | **雙客戶 demo 組裝 + 驗 RLS 分流 + 收尾文件** | ⏳ **進行中** | — |

## 文件 commits（BE）

| Commit | 內容 |
|--------|------|
| `f3e0bfd3` | docs：design.md / implementation-plan.md / proposal.html（設計規格 v2）|
| `1fb88622` | feat：Phase 2 RemoteAgentAdapter + Phase 3 SHA-256 |
| `fa5f3fec` | feat：file_agent registry 後端 |

## 目前 demo 實況（dev 環境）

- **121 agent 已部署且運作**：`http://192.168.50.121:8080`（minio 模式，bucket `guidant-ai`）；本機直接打 `/blob` 上傳成功。
- **122 尚未部署**。
- **dev DB（188/guidant_ai_dev）已 seed**：
  - `compliance.file_agents`：`agent-cust-a-121`（→121）、`agent-cust-b-122`（→122），tenant 102。
  - tenant 102 的 `STORAGE_CONFIG` = `{"storage_type":"remote_agent","agent_uid":"agent-cust-a-121"}`。
- **已實測**（102 登入上傳/預覽走完整鏈）：上傳→121 MinIO ✅、下載 ✅、**預覽出 PDF ✅**（修了 EXDEV）。

## 2026-06-18 晚更新（demo 測試踩到的 + 修法）

| # | 問題 | 修法 | 狀態 / 還要做 |
|---|------|------|---------------|
| Bug 2 | minio 預覽 500 `os.replace … EXDEV` | `PDF_CACHE_DIR` 從 bind-mount `/data` 改 `/tmp/pdf-cache`（裝置一致）；套件 `minio_adapter` `os.replace`→`shutil.move`（根治）| ✅ **預覽已出 PDF**（commit evidence-agent `7f2d91a`）|
| **中文字型** | 轉檔後**中文變空白/豆腐字** | Dockerfile 加 `fonts-noto-cjk` | ✅ **已部署 121 + 驗中文 OK**（2026-06-19；amd64 image 重 build → save → load 121）|
| Bug 1 | 刪程序書沒刪 minio 物件（孤兒）| `delete_from_pool` 經 `file_upload_service.delete_file`→adapter 真刪；**修刪除順序**（先刪 pool 紀錄解 FK 再刪實體檔，否則 FK violation 毒化 transaction 回 500）| ✅ **已驗刪除 OK**（BE commit `fb54d97d`，supersede `931e44a7`）|

**新增 commit**：BE `931e44a7`（Bug 1）、evidence-agent `7f2d91a`（Bug 2 + 字型）。

**未 commit（jedi-file-upload 套件 working tree，發版/path-dep 才生效）**：
- `infra/mapper/upload_file_mapper.py`：`to_entity` 補 `checksum`（讓防竄改 live）
- `infra/adapter/minio/minio_adapter.py`：`os.replace`→`shutil.move`（EXDEV 根治）
> 查看：`git -C ~/Projects/Jedicogy/module/jedi-python-package/jedi-file-upload status`

## 未完 / 待辦

| 項目 | 說明 |
|------|------|
| Phase 4 e2e（FE）| 重啟 BE → 102 登入上傳新檔 → 驗證進 121 MinIO + 下載/預覽；測完還原 102 config |
| 部署 122 | 同 121 流程，`.env` 的 `MINIO_ENDPOINT` 改 122 |
| 防竄改生效 | jedi-file-upload mapper 補 `checksum`（**未 commit、在套件 working tree**）要 dev path-dep 或發版才 live；未 live 時整性 fail-open |
| 管理 UI | registry 的 CRUD 頁（擴 FE `StorageConfigForm.vue` + agent 下拉）後補 |
| **刪檔留 PDF 快取孤兒** | 刪 docx 等「會轉檔成 PDF 預覽」的檔時，目前只刪儲存後端原始物件，**agent 端轉檔產生的 PDF 快取（`PDF_CACHE_DIR=/tmp/pdf-cache`，以 file uid 為 key）沒被清** → 留孤兒 PDF。要在 agent 的 `delete_file` 流程順帶清掉對應快取項（或刪檔時通知 agent invalidate 該 uid 的轉檔快取）。2026-06-19 user 回報 |
| migration 多環境 | `2026-06-18-fr039-file-agents-table.sql` + `2026-06-18-fr039-storage-type-remote-agent-menu.sql` 只套了 dev；stg/poc/prod 待 |
| demo 後強化 | `upload_files` tenant_id/RLS、加密、cloud↔agent 認證 key、獨立 `sha256` 欄、agent 健康檢查/對帳、agent DB 備份 |
| 收尾文件 | changelog / conversation-history / Notion 待（FR-039 真正 ship 時補）|

## 跨 repo 座標

| repo | branch | 路徑 |
|------|--------|------|
| BE | `feature/FR-039-evidence-agent` | `~/Projects/Billows/Audit-Manager/compliance-manager-be` |
| evidence-agent | `feature/FR-039-evidence-agent` | `~/Projects/Billows/Audit-Manager/evidence-agent` |
| jedi-file-upload | （套件 working tree 有未 commit mapper 改）| `~/Projects/Jedicogy/module/jedi-python-package/jedi-file-upload` |
