# FR-039 隔夜工作紀錄（2026-06-19 凌晨）— 給早上驗收

> 接續前一段 session（中文字型部署、刪除 bug、storage-config remote_agent、jedi-file-upload 0.0.17 發版）。
> 本紀錄涵蓋 user 交辦的兩件事：**deploy 雙模式** + **registry 管理 UI**。branch 全在 `feature/FR-039-evidence-agent`，**未 push**。

> ⚠️ **早上追加：file_agent 全面正名為 remote_agent**（見文末 §C）。下面 B 段提到的
> `file_agents` 表 / `file-agent-manage` 選單 / `/file-agents` endpoint **都已改名**為
> `remote_agents` / `remote-agent-manage`（選單顯示「Agent 管理」）/ `/remote-agents`。

---

## A. Deploy 可切 local / minio（evidence-agent）

**背景**：agent code 早就支援 local 落地存檔（`config.py` 預設就是 local），但 `deploy/` 只 wire 了 minio，且 file-agent 沒掛 volume → 切 local 會檔案不持久（容器重建即遺失）。

**做了**：
- `deploy/docker-compose.yml`：`STORAGE_TYPE` 改 env-driven（`${STORAGE_TYPE:-minio}`）；補 `BASE_DIR`；file-agent 加 `./filedata:/data/upload` 持久 volume；`MINIO_*` 改 `:-` 預設空（local 模式可不填）。
- `deploy/.env.example`：分 minio / local 兩段說明 + `STORAGE_TYPE` 切換。
- 驗證：`docker compose config` 兩種模式都 parse 過。

**commit**：evidence-agent `3ca2536`

**怎麼用 local 模式**：`.env` 設 `STORAGE_TYPE=local`（minio 那幾行可留空）→ `docker compose up -d`。檔案落在 `./filedata`。

---

## B. Registry 管理 UI（BE CRUD + RLS + FE 管理頁 + 權限）

讓管理者在 UI 上 CRUD 客戶端檔案 agent（原本只能灌 SQL）。

### B1. BE CRUD + per-tenant RLS（commit `2840c9d8`）
- 新 routes：
  - `POST /api/1.0/file-agents`（新增）
  - `GET /api/1.0/file-agents/all`（管理列表，含停用，完整欄位）
  - `GET / PUT / DELETE /api/1.0/file-agents/<uid>`（detail / 更新含啟用切換 / 刪除）
  - （既有 `GET /file-agents` 仍是 storage-config 下拉用，只回啟用中 uid+name）
- app service `FileAgentService`：list_all / get / create / update（部分更新）/ delete。domain service 補 create/update/delete。
- **RLS**：建表時 RLS 暫緩，本次補 `file_agents` per-tenant RLS policy（比照 `devices`）。
  - migration `2026-06-19-fr039-file-agents-rls.sql`
  - **已套 dev + cm_app 隔離測試通過**：本租戶可見/可寫、他租戶 0 筆、建立自動補 tenant_id（db_mw before_flush）。
- error code：`FILE_AGENT_NAME_REQUIRED` / `BASE_URL_REQUIRED`（400）。

### B2. FE 管理頁（compliance-manager-fe，待 commit）
- `src/views/file-agent/FileAgentManage.vue`：DataTable（client-side，registry 筆數少不分頁）+ 新增/編輯 Dialog + 啟用 InputSwitch 即時切換 + 刪除確認。
- `api.js`：加 `FILE_AGENTS_ALL`。
- i18n：`zh-tw/file-agent.json` + `en/file-agent.json` + 註冊進 `locales/index.js`；`menu.json` 加 `file-agent-manage` 標籤。
- `router/index.js`：加 `/system/file-agent-manage` route。

### B3. 納入權限/選單系統（commit `2840c9d8` 同批，migration）
- migration `2026-06-19-fr039-file-agent-manage-permission.sql`：比照 storage-config 的 RBAC 三層
  - `ui_routes`（pid=46 系統設定群組，sort=45，介於 storage-config 與 cloud 之間）
  - `capabilities`（read/create/update/delete 4 個）
  - `route_capabilities`（read=ALL 其餘=ANY）
  - `role_capabilities`（授予 roles 2/3/37/38：Administrator / Billows Admin / IT執行人員 / Billows 系統管理員）
- **已套 dev**，驗證 blsadmin（role 3 Billows Admin）拿到 route + 4 capabilities → 選單會出現「檔案 Agent 管理」。

---

## 早上驗收 checklist

> **前置**：BE 要重啟（新增 route 模組 + DI）；FE 重新整理（router/i18n/menu 改動）。

### deploy（A）
1. （可選）拿一台測試 server 或本機，`.env` 設 `STORAGE_TYPE=local` → `docker compose up -d` → 上傳檔案 → 重建容器（`docker compose up -d --force-recreate`）→ 檔案仍在（`./filedata` 持久）。

### registry 管理 UI（B）
2. blsadmin 登入 → 左側「系統設定」群組應出現 **檔案 Agent 管理**（在「儲存設備設定」附近）。
3. 進該頁 → 應列出 tenant 102 既有 2 個 agent（客戶A-121 / 客戶B-122）。
4. **新增**：填名稱 + base_url（如 `http://192.168.50.123:8080`）→ 儲存 → 列表多一筆。
5. **編輯**：改名稱 / base_url → 儲存 → 列表更新。
6. **啟用切換**：切某 agent 的 InputSwitch → toast 成功；回 storage-config 頁的 agent 下拉，停用的不應出現（只列啟用中）。
7. **刪除**：刪一筆 → 確認框 → 列表移除。
8. **租戶隔離**（如有第二租戶帳號）：另一租戶看不到 102 的 agent。

---

## 決策紀錄（為何這樣做）

- **管理列表用簡單 GET /file-agents/all 不分頁**：registry per-tenant 筆數很少（個位數），client-side DataTable 足夠，省掉 lazy pagination 複雜度。
- **回應不含 created_user/updated_user**：避免觸發「審計欄位須附 nickname」需注入 User service 的成本；管理頁顯示 name/base_url/type/enabled 已足夠。要的話再補 enrichment。
- **補 RLS（非延後）**：管理 UI 是真功能非單租戶 demo，不補 RLS 會跨租戶看到彼此 agent。比照 devices pattern，tenant-only（file_agents 非 org-scoped，insert WITH CHECK 不加 org 檢查）。
- **權限比照 storage-config**：同屬系統設定群組、同一批管理角色，直接 mirror 它的 capabilities/role 授權，行為一致。
- **BE 寫入權限**：沿用 storage-config 的 `@jwt_required`（無額外 role decorator）；存取控制走 RBAC 選單層（只有被授權角色看得到頁面）。與既有系統設定頁一致。

---

## 待辦 / 注意

- **migration 多環境**：本次新增 3 支 migration（`file-agents-rls` / `upload-files-add-sha256`（前段）/ `file-agent-manage-permission`）+ 前段 `storage-type-remote-agent-menu` 都只套了 **dev**；stg/poc/prod 待。
- **FE 未 commit**：FileAgentManage 頁 + api/i18n/menu/router 改動還在 working tree（等驗收過再 commit，或你說 commit 我就 commit）。
- **push 全部等 user 明示**（BE / FE / evidence-agent / jedi-file-upload gitlab）。
- **jedi-file-upload 0.0.17** 已推 Nexus；BE/agent 已 pin（前段紀錄）；gitlab push 待 user。

---

## C. file_agent → remote_agent 全面正名（2026-06-19 早上）

未來多種 agent（以 `agent_type` 區分）並存，把 file-specific 命名正名為通用 `remote_agent`
（與既有 `RemoteAgentAdapter` / `REMOTE_AGENT` storage_type 一致）。選單顯示文字用「Agent 管理」。

| 層 | 改名前 → 改名後 |
|----|----------------|
| DB table | `compliance.file_agents` → `compliance.remote_agents`（+ 序列/索引/RLS policy/grant）|
| BE endpoint | `/file-agents*` → `/remote-agents*` |
| BE 模組 | `file_agent`（api/app/domain/infra/di）→ `remote_agent`；類名 `FileAgent*` → `RemoteAgent*` |
| RBAC 選單 | `file-agent-manage` → `remote-agent-manage`（url `/system/remote-agent-manage`）|
| FE | `views/remote-agent/RemoteAgentManage.vue`、`REMOTE_AGENTS*`、i18n `remote_agent_manage`，選單字串「Agent 管理」|
| error code | **保留** `FILE_AGENT_*`（內部碼、非對外標籤）|

- migration：`2026-06-19-fr039-rename-file-agents-to-remote-agents.sql`（已套 dev；冪等 RENAME）。
- 驗證：BE 模組 import OK + tablename=remote_agents；cm_app RLS 測試在 remote_agents 上仍隔離正確（本租戶 2 筆）；FE build exit 0。
- **commit**：BE `50931d90`、FE `e6c0ff5`。

### 早上驗收補充
- 選單項應顯示 **「Agent 管理」**（不再是「檔案 Agent 管理」），URL `/system/remote-agent-manage`。
- 其餘 CRUD / 啟用切換 / 刪除驗收同 B 段（endpoint 已是 `/remote-agents`）。

### ⚠️ 注意
- 此 rename migration **需 BE 同步上新版**（model `__tablename__='remote_agents'`），否則舊 code 查 `file_agents` 會 UndefinedTable。dev 已對齊。
- stg/poc/prod：原 file_agent 系列 migration + 本 rename migration 依序套即達末態 `remote_agents`。
