# FR-169 下載檔加密 — STATE（living，只描述此刻）

> 2026-10-29 晚：十張卡驗收通過並合回；決策者實測抓到證據附件漏接，首腦直修；容器 7z → AES-256 zip；批 7～8 兩張套件匯出補卡待派。「還是有問題」已問清：PDF／Office 預覽哭臉是 FR-166 回歸、已修（FE `72ed484c`）；PDF 預覽藏瀏覽器下載／列印工具列（FE `03e6acfb`，主控台 `dist-console` 已重 build）；決策者兩項都手測 OK。本機 Agent 登不進去由另一個 session 處理，本案不追。**2026-10-29 決策者收 Done：母卡 CM-3223 與十二張子卡全部 Done。** 本案開發完成，剩上版類動作（見 §4）。

## 🧭 原始需求

檔案下載到電腦後別人雙擊就能看。終局：Word／Excel／PDF 用格式內建開啟密碼、檔名照原樣；其他格式與多檔打成 AES-256 zip，外層檔名去掉原副檔名（`截圖.zip`）、裡面保留原檔名、檔名清單明文（決策者接受）。密碼瀏覽器端產、畫面只顯示一次、放 header `X-File-Password`；使用者永遠不能選不加密；管理員一個開關預設開，關閉寫稽核＋系統管理員全站頂部常駐橫幅（「畫面上標未加密」裁示不做，系統沒有稽核事件頁）。

## 1. 現況

| 項 | 狀態 |
|---|---|
| 子卡 | CM-3224～3231、CM-3280～3281、CM-3286～3287 共十二張與母卡 CM-3223 皆 Done |
| 合回 | 四 repo `ws-CM-3223` 已全部合進 `feature/FR-139`（工作區可由工作坊「結案」移除） |
| 首腦直修（不在卡上） | ①上傳檔下載（證據、程序書、前置資料、問卷與意見回饋附件）接 send_protected：jedi-file-upload 1.5.0 `download_responder`、BE `core/plugins/_file_upload_download.py`、FE 12 處改走 `useProtectedDownload.downloadFile`、簽票明文路徑刪除 ②上傳檔不自動拆 zip（zip 炸彈）③容器 7z → AES-256 zip（jedi-file-protect 0.2.0）④包 zip 的外層檔名去副檔名（0.2.1） |
| 套件（Nexus 已發） | jedi-file-protect 0.2.1、jedi-iam 1.10.0、jedi-masking 0.1.1、jedi-file-upload 1.5.0、jedi-log 1.4.0、jedi-issue 1.5.0、jedi-task-platform 1.5.0；BE 皆已釘版（`pyproject.toml`），Agent 釘 jedi-file-protect `>=0.2.0,<0.3`、jedi-masking 0.1.1、jedi-file-upload 仍 0.0.22（另一條舊線，不動） |
| 8000 | 跑 BE `c9bbd014f`＋釘版套件（PID 13646）；worker 41809 未重啟（不吃本案） |
| 測試 | 套件 38；BE helper＋守衛 132；Agent 19（全量 1674 在 A1 合回時過）；FE 367＋build 過 |
| DEV 實打 | 風險總表 xlsx、證據 docx 原生加密；證據 png → `…截圖.zip` 內 `…截圖.png` AES-256；無密碼 400 GRC_400190；稽核 FILE_DOWNLOADED 帶 source；log 無密碼 |
| push | BE、FE、套件三 repo 已 push 到 `feature/FR-139`（Agent origin 本來就同步）；BE working tree 另有 FR-166.1 首腦未 commit 的 jedi-detection path 改動（不是本案） |
| 對話框 | zip 情況只剩一個橘框（密碼只顯示一次＋要用什麼工具開），FE `f48b57f0`；非 zip 情況藍框＋一行開啟方式 |
| 預覽 | PDF 預覽無瀏覽器工具列、列印空白（FE `03e6acfb`）；sandbox 回歸已修（`72ed484c`）；兩項決策者手測 OK |
| 系統回饋頁 | 白畫面已修（漏 import，FE `257b52dc`）；加守衛測試防同類漏 import |
| 批 7～8 | CM-3286（套件掛點，`aad916f4`／`5230800d`／`9cda814e`）、CM-3287（BE 注入＋釘版，`b16f053a5`／`c9bbd014f`）首腦直做；三支套件已發版；FE 不用改；Done |

## 2. 本棒紀律（沿用）

對外可見的改動（格式、檔名、文字、對話框）動之前先講三句給決策者：使用者會看到什麼、哪一層鎖了、哪一層沒鎖，說好再改。測試只做修正本身與必要守衛，不加碼（決策者 2026-10-29 指示「我會手動測試」）。

已處理：①PDF／docx／xlsx 預覽哭臉——不是本案，是 FE `FilePreviewPane.vue` iframe `:sandbox` 綁定在真瀏覽器變成 `sandbox="undefined"`（FR-166 CM-3198 回歸、jsdom 測不出），改 `:sandbox.attr`，FE `72ed484c`。②PDF 預覽藏掉 Chrome／Edge 內建檢視器工具列（`#toolbar=0`）、列印印空白，主站與主控台都改，FE `03e6acfb`；主控台靜態包 `dist-console` 已重 build（不入版控，換機要再 build）。決策者兩項手測 OK。擋不住右鍵／Ctrl+S，要全擋是 pdf.js 自繪，未開卡。

不歸本案：本機 Agent 主控台登不進去，決策者另開 session 處理，本案不碰。

## 3. 驗收

決策者 2026-10-29 裁示原列的三項未驗（Word／Acrobat／解壓工具實際開檔、真機 Agent 稽核 `encrypted=true`、關閉保護後全站橫幅實看）當作驗過。真機 Agent 那項實際要等 Agent 以新程式出包部署後才看得到，出包時順手確認。

## 4. 剩下的上版事項（等決策者）

1. Agent image 出包（Nuitka 要確認 pyzipper、msoffcrypto、reportlab 被收進去）。
2. 出包前基線重產（seed 守衛兩顆能力點缺 `04-seed-core.sql`，FR-166.1 遺留）。
3. STG／POC 上版。
4. 想把預覽的右鍵／Ctrl+S 也擋掉，另開 pdf.js 自繪卡（未排）。
5. **預覽端點直接打網址拿得到未加密的 PDF**（有預覽權限即可）。方向二選一等決策者裁：預覽也要下載權限（改動小、分權消失）／預覽改圖片或 pdf.js 自繪（改動大）。
6. 「哪些出口要加密」的類別設定（證據強制加密）：決策者裁示先不做。現行不加密名單寫死在程式：責任分工設定、控制項對照、任務批次。

## 5. 已知代價（已寫進 SPEC 七頁、手冊、對話框、design D3）

- zip 檔名清單不用密碼看得到，內容要密碼；檔名不要放機密。
- Windows／macOS 內建解壓打不開 AES zip（只認已被破解的 ZipCrypto），仍要裝 7-Zip／WinZip／Keka／The Unarchiver。

## 6. 環境座標

DEV：BE localhost:8000（`main.py`，重啟只 kill 核過的 PID）、DB localhost:5432 `guidant_ai_dev`；測試帳號見 `docs/claude/memory/reference_dev_login.md`。套件源碼 `~/Projects/Jedicogy/module/jedi-python-package/jedi-file-protect`（測試用 BE 的 venv 跑：`env -u VIRTUAL_ENV ~/Projects/Billows/Audit-Manager/compliance-manager-be/.venv/bin/python -m pytest`；套件自己的 venv 缺 jedi-common plugin 子包）。突變測試還原用 `git checkout -- <檔>`，不要 `cp`（舊 pyc 會繼續被用）。文件站 `python scripts/deliverables/render_index.py docs/features/FR-169-2610-download-file-encryption/`。
