# v1.12.0 發版全紀錄 + FR-057 全案收尾 SUMMARY（2026-07-30）

> 本文是 FR-057（OpenSCAP SSH connector）全案收尾彙整：v1.12.0 發版座標、發版過程時間線（含 tag 重打緣由）、上線驗證期三項修正的完整故障分析、部署現況、已知 follow-up 與 Notion 全案卡號結案清單。功能本體內容見 `docs/release_notes/v1.12.0.md` 與同目錄 `2026-07-29-fr057-arc-complete-handoff.md`（已加結案標頭）。

## 1. 發版座標（三 repo + 套件）

| Repo / 套件 | 版本 | 最終 commit / tag | 備註 |
|------|------|------|------|
| compliance-manager-be | v1.12.0 | `6b8023be`（tag `v1.12.0`，已 push） | `pyproject.toml` version = 1.12.0 |
| compliance-manager-fe | v1.12.0 | `34ed5ec`（tag `v1.12.0`，已 push） | `chore: 版號對齊 BE v1.12.0` |
| evidence-agent | 0.2.11 | `722e25ca`（已 push） | 0.2.9 → 0.2.10（CM-952）→ 0.2.11（CM-954），部署直接跳最新 |
| jedi-common | 0.0.30 | `fd97f97`（修正）+ `f12a985`（bump），**已發 Nexus** | CM-955：HTTPException handler；BE pin bump 在 `ab4a7091` |

## 2. 發版過程時間線（含 tag 重打）

| 時間 | 動作 | commit |
|------|------|--------|
| 07-29 | **進版**：release note `docs/release_notes/v1.12.0.md` + `pyproject.toml` bump 1.12.0 + `docs/specs/v1.12.0/` 凍結快照（version-bump skill 全套） | `bed69767` |
| 07-29 | tag `v1.12.0` **首打**於 `bed69767`（尚未 push） | — |
| 07-29 晚 | 上線驗證期發現修正 ①：工具設定寫入守門下放（未開卡） | `fabf974e` |
| 07-29 深夜 | 上線驗證期發現修正 ②：背景 job 檔案存錯租戶儲存後端（預覽 500） | `d20ac604` |
| 07-30 | release note 修訂——併入上線驗證期兩項修正；tag 重打 | `0875e5b0` |
| 07-30 | 上線驗證期修正 ③：jedi-common 0.0.30 發版（CM-955，404 回 500）+ BE pin bump；tag 重打 | `ab4a7091` |
| 07-30 | release note 相依套件段補 jedi-common 0.0.30；tag **最終落點** + push | `6b8023be` |

**tag 重打緣由**：首打後、push 前，上線驗證期陸續發現三項必要修正——tag 尚未推出去，把修正折進同一版重打 tag，比為三個 fix 另開 v1.12.1 乾淨（版本語意上這三項都屬 v1.12.0 的上線品質保障，非新功能）。最終 tag `v1.12.0` = `6b8023be`，已 push。

## 3. 上線驗證期三項修正（問題 / 根因 / 修法 / 驗證）

### 3.1 工具設定寫入守門下放（BE `fabf974e`，未另開 Notion 卡）

- **問題**：檢測工具設定的新增 / 更新 / 重置憑證只有系統層 super_admin（tenant admin）能操作，一般被授權管理者存不了設定。
- **根因**：FR-056 上線時本模組租戶層 capability 未 seed，寫入動作以 service 層帳號級 `require_super_admin()` 過渡守門（設計上就是暫時方案，見 FR-056 design D6 附註），一直沒回頭下放。
- **修法**：route 層三端點（create / update / reset）掛 `@require_capability("plugin.update")`——tool-plugin-manage 頁對應的**既有** `plugin.*` capability，角色權限矩陣「檢測工具管理」列有 update 勾即可操作；super_admin 保留 break-glass 放行；service 層 `require_super_admin()` 與 import 移除。符合 FR-048 授權守門雙軌規範（主體域守門允許 route decorator 形式）。
- **驗證**：**無 migration**——`plugin.*` capability 三環境（DEV/STG/POC）已存在且已配角色，實查確認後直接復用。測試 `test/test_tenant_detection_tool_config_service.py` 移除 super_admin patch fixture（守門已不在 service 層）。
- **改動檔**：`api/detection_tools/routes/detection_tool_route.py`（三端點掛 decorator）、`app/detection_tools/service/detection_tool_service.py`（移除守門）、`test/test_tenant_detection_tool_config_service.py`。
- **spec**：`docs/specs/current/system-admin/tool-plugin-manage.md` §1/§2/§3/§8/§12/§13 已同步更新（本次收尾）。

### 3.2 背景 job 上傳檔案存進別租戶儲存後端（BE `d20ac604`，CM-956）

- **問題（症狀）**：POC 任務抽屜**預覽** OpenSCAP 掃描報告回「查無檔案」（BE 500，`FILE_UPLOAD_500002`）；**下載**同一檔卻正常。Drive 自動同步的檔案同根因。
- **根因**：detection 報告回收鏈（`detection_result_handler`）與 Drive 同步鏈（`import_drive_file_handler`）都是背景 job，以系統服務身分（無 JWT、無租戶脈絡）呼叫 `upload_files()`。`ManagedFileUploadService._load_config` 走 `get_system_config_by_key` 單筆解析，無 RLS 脈絡時不 filter tenant、`order_by(id).first()` **非確定性**挑設定——POC 挑到 tenant 1 的 minio 設定，把 tenant 102 的檔存進別租戶 bucket。預覽帶 JWT → RLS 收斂到 tenant 102 → 只見 remote_agent 設定 → minio 型檔案查無同型設定 → `_caller_adapter_for_entity` 拋 500；下載無 JWT 繞 RLS 看得到全部設定，storage_type 過濾找到 minio 而成功——這就是「預覽壞、下載好」的不對稱。
- **修法（三件）**：
  1. **寫入端治本**：新增 `upload_files_for_tenant(tenant_id=...)`，以「該 job 所屬租戶」的 STORAGE_CONFIG 解析上傳後端——detection 走 `agent.tenant_id`、drive 走 `job.tenant_id`。繞 RLS 讀設定複用既有 root reader 樣板；per-tenant adapter 每次新建、**不寫入全域 lazy singleton 快取**（避免污染後續一般請求）。
  2. **讀取端容錯**：`_caller_adapter_for_entity` 在本租戶查無同型設定時，跨租戶（繞 RLS）by-type fallback 借同型設定端點/憑證 + 用**檔案自記 path** 覆寫位置——既有錯位檔案**不需搬家即恢復預覽**。
  3. **infra reader 擴充**：`system_config_root_reader` 新增 `read_tenant_config_value` / `read_all_config_values`，與 root 讀取共用同一份繞 RLS session 樣板（禁止另寫第二份）。
- **驗證**：POC 三筆 CM case 主角報告（OpenSCAP 掃描報告 _151/_188/_189，存錯進 minio `guidant-ai-dev` bucket）修正部署後預覽恢復。
- **錯位存量（未搬家，容錯已可讀）**：

  | 環境 | 錯位檔數（distinct file_id） | 來源分佈 |
  |------|------|------|
  | DEV | 21 | DRIVE_SYNC 21 |
  | STG | 0 | — |
  | POC | 143 | DRIVE_SYNC 137、DETECTION_TOOL 6 |

  所有錯位檔所屬租戶皆為 102（設定 remote_agent），實際落在 minio（`guidant-ai-dev`/`-stg` bucket）。POC 143 筆 > 停損線 50，**未執行批次搬家**，逐筆清單在收尾當時 session 的 scratchpad（`INVENTORY-SUMMARY.md` + `mismatch-inventory.txt`，摘要已抄錄於此；scratchpad 為暫存區，正式搬家前需重新盤點確認）。搬家是把檔搬回「正確後端」的清理，非恢復預覽的前置。

### 3.3 CM-955：不存在的 URL 回 500 而非 404（jedi-common 0.0.30）

- **問題**：OpenVAS 弱掃探測不存在的路徑時，BE 對 404/405 一律回 500，弱掃報告多記一堆假 server error，且 log 被 ERROR + traceback 洗版。
- **根因**：jedi-common error handler 的 `Exception` catch-all 把 werkzeug `HTTPException`（404/405 等框架原生例外）也吞進去壓成 500。
- **修法**：jedi-common `fd97f97`——補 `HTTPException` 專屬 handler，保留原生狀態碼；同時 error_handler logger 的 dev/prod config level ERROR→WARNING（否則新 handler 記的 warning 被吞看不到）。consumer 升版後會多出此類 WARNING 輸出，屬預期。
- **發版**：jedi-common bump 0.0.30（`f12a985`）已推 Nexus；BE pin bump `ab4a7091`。
- **驗證**：升版後對不存在路徑請求回 404、log 單行 WARNING。

## 4. 部署現況（2026-07-30）

| 項目 | 狀態 |
|------|------|
| BE + FE（DEV / STG / POC） | 三環境皆已部署 v1.12.0（user 自行操作） |
| evidence-agent | 0.2.11 已部署 @121 / @122 / @123 |
| DB migration（3 支，見 release note §5） | DEV / STG / POC 三環境已全數套用（`schema_migrations` 記帳） |
| POC FR-048 capability seed | 已補（守門下放依賴 `plugin.*` capability 存在，POC 缺的 seed 已補齊） |

## 5. 已知 follow-up

| # | 項目 | 狀態 |
|---|------|------|
| 1 | **錯位檔案批次搬家**：POC 143 / DEV 21 筆（見 §3.2 表），讀取端容錯已可讀故不急迫；搬家屬清理性質，超停損線待 user 裁決 | 未執行 |
| 2 | **CM-953**：Windows / 異質 OS 目標主機支援 | 討論中，待拍板是否開獨立 FR |
| 3 | **CM-937（FR-056.9）**：Agent 心跳自報 capabilities（取代手動改 DB） | 未開工 |
| 4 | `main_app.py` 加 `load_dotenv()` | 方向已拍板，未開卡 |
| 5 | **失敗主機部分重掃**：目前單台失敗只能整批全部重掃 | 未開卡 |
| 6 | **rebuild.sh `--platform` 保護**：agent 跨平台 build（Mac arm64 → amd64）缺 `--platform linux/amd64` 會產出跑不動的 image，build 腳本應內建保護 | 未開卡 |

## 6. Notion 全案卡號結案清單

| Case | 內容 | 最終狀態 |
|------|------|---------|
| CM-938 | FR-057 母案 | Done |
| CM-939 / 940 / 941 | FR-057.1（BE 地基）/ .2（Agent connector）/ .3（多檔回收鏈）子需求卡 | Done |
| CM-942 ~ 949 | T-1.1~1.3（migration + FE）+ T-2.1~2.3（connector）+ T-3.1~3.2（多檔回收） | Done |
| CM-950 / 951 | T-2.2-fix（遠端暫存改家目錄 mktemp）/ T-2.3-fix（probe 測試主機） | Done |
| CM-952 | 多台掃描結果呈現不完整（漏掃靜默 / 報告只拿一份 / 執行紀錄不展開） | Done（agent 0.2.10 起） |
| CM-953 | 異質 OS（Windows）支援方案 | **討論中**（唯一未結案） |
| CM-954 | content 與目標 OS 不匹配產出假成功報告 | Done（agent 0.2.11） |
| CM-955 | 不存在的 URL 回 500 而非 404 | Done（jedi-common 0.0.30） |
| CM-956 | 背景 job 上傳檔案存進別租戶儲存後端（預覽 500 / 下載正常） | Done（BE `d20ac604`） |

## 7. 相關文件索引

- Release note：`docs/release_notes/v1.12.0.md`（= `docs/specs/current/release-notes/v1.12.0.md`）
- 凍結快照：`docs/specs/v1.12.0/`
- arc 收官 handoff（功能全貌 + 部署教訓，已加結案標頭）：同目錄 `2026-07-29-fr057-arc-complete-handoff.md`
- 設計文件：`docs/features/FR-057-2607-openscap-ssh-connector/design.md`
- 使用手冊：`docs/features/FR-056-2607-detection-tool-integration/user-manual.html`
- 本版更新頁面 spec：`docs/specs/current/system-admin/tool-plugin-manage.md`（含 2026-07-30 守門下放）、`project-management/project-task-edit.md`、`audit-execution/my-tasks.md`
