# Shared Drive File Access 驗收矩陣（MVP）

## 驗收目標
確認共享槽找檔 / 選檔 / 打包 / 24h 下載連結 / 敏感加密在 MVP 階段可正常運作。

---

## A. 索引與查找

### A1. 可建立索引
- 條件：指定 root 或自訂 sandbox root
- 預期：`shared_drive_index_build.py` 成功寫入 DB 與 FTS
- 驗證：
  - `files > 0`
  - `files_fts > 0`

### A2. 可查到資料夾候選
- 條件：查詢詞命中資料夾名
- 預期：回傳資料夾候選，`is_dir = true`

### A3. 可查到檔案候選
- 條件：查詢詞命中檔名或摘要
- 預期：回傳檔案候選，含 Mac/Windows 路徑、mtime、summary

### A4. FTS miss 時可 fallback lookup
- 條件：FTS 未命中但檔名/路徑可命中
- 預期：`shared_drive_lookup.py` 回傳 `mode = shared_drive_lookup_fallback`

---

## B. 交付與下載

### B1. 單一低風險檔案可直接交付
- 條件：text / low sensitivity / 1 file
- 預期：
  - `artifact_type = file`
  - `encrypted = false`
  - `download_url` 存在
  - `verification.ok = true`

### B2. 敏感檔會改走加密 zip
- 條件：命中 email / phone / finance keywords
- 預期：
  - `artifact_type = zip`
  - `encrypted = true`
  - `password` 存在
  - `password_channel` 存在
  - `verification.ok = true`

### B3. 多檔打包
- 條件：2~10 檔
- 預期：
  - 一律 zip
  - 若其中一檔敏感，整包 `encrypted = true`

### B4. 超過 10 檔 fail closed
- 條件：一次傳入 >10 檔
- 預期：腳本直接拒絕執行

### B5. 下載連結不得被省略截斷
- 條件：回覆中提供下載網址
- 預期：
  - 使用者看到的是**完整網址**
  - 不得出現 `...` / `…` 導致 token 中段被截斷
  - 優先使用短碼型下載網址（例如 `/downloads/s-<short_id>`）
  - 若平台容易截斷，優先改走直接附件或其他不會截斷的交付方式

### B6. 回覆需支援數字序號互動
- 條件：候選清單 / 資料夾展開 / 下一步建議
- 預期：
  - 候選項目有清楚序號
  - 使用者可直接回 `1` 或 `1 3 5` 進行下一步
  - 回覆中明講數字對應動作（展開 / 選檔 / 打包）

---

## C. Token 與路由

### C1. token 可在本機 resolve
- 驗證：`resolve_signed_download_token(token)` 能解析到 staged file

### C2. 本機 `/downloads/{token}` 可成功下載
- 驗證：FastAPI TestClient GET `200`
- 預期：`Content-Disposition` 為 attachment

### C2a. 本機短碼 `/downloads/s-<short_id>` 可成功下載
- 驗證：FastAPI TestClient GET `200`
- 預期：`Content-Disposition` 為 attachment

### C3. 外部 public URL 可用 GET 驗證
- 驗證方式：使用一般 GET 客戶端（例如 requests / curl GET）
- 預期：`200`

### C4. 不以 HEAD 當成功判準
- 原因：目前 public `/downloads/{token}` 僅註冊 GET；HEAD 可能 `405`
- 規則：MVP 驗收以 **GET** 為準，不以 HEAD 失敗視為下載壞掉

### C5. 不以 Python urllib 預設 UA 的 403 當最終失敗判準
- 原因：Cloudflare 可能對部分 bot-like UA 回 `1010` / `403`
- 規則：驗收以一般 GET client 與實際瀏覽器可開啟為準

---

## D. 清理

### D1. manifest 存在
- 預期：每個新 bundle 目錄有 `manifest.json`

### D2. cleanup 可辨識過期 bundle
- 驗證：`shared_drive_cleanup.py --dry-run`
- 預期：
  - 未過期 bundle 出現在 `kept`
  - 過期 bundle 出現在 `removed`（dry-run 僅模擬）

---

## E. 目前已知限制
1. Windows 路徑轉換目前對自訂 sandbox root 仍會顯示 `（路徑轉換待確認）`
2. 敏感判斷目前為規則式，不是完整版 classifier
3. 目前未做正式 audit DB，只先寫 `manifest.json`
4. 資料夾→最多 10 檔的「對話層 UI」仍需在 chat 回覆模板上補齊

---

## 建議驗收指令
```bash
python3 ~/.hermes/scripts/shared_drive_index_build.py --reset
python3 ~/.hermes/scripts/shared_drive_index_query.py status
python3 ~/.hermes/scripts/shared_drive_lookup.py 關鍵字
python3 ~/.hermes/scripts/shared_drive_delivery_bundle.py --paths /absolute/file --requester dk96@bremen.com.tw
python3 ~/.hermes/scripts/shared_drive_cleanup.py --dry-run
```
