C7 — Implementation Plan

對應 design:design-C7.md 級別:小 預估工時:BE 0.5 天(含 smoke + 樣板版本確認)


§1

Pre-flight 驗證

# 1. 確認 SHEET_LEVERAGED 定義仍在
grep -n "SHEET_LEVERAGED" app/module_frame/excel_template/sheet_definitions.py
# 預期:line 184

# 2. 確認 parse_leveraged_sheet handler 仍在
grep -n "parse_leveraged_sheet" app/oscal/service/excel_parser/sheet_handlers.py
# 預期:line 139

# 3. 確認 LeveragedWriteStrategy 仍存活
grep -rn "LeveragedWriteStrategy\b" app/oscal/service/ --include="*.py" | head -3
# 預期:被 ssp_excel_import_app_service.py 注入

# 4. 樣板版本目前值
grep -n "TEMPLATE_VERSION\b" app/module_frame/excel_template/sheet_definitions.py
# 預期:v2.0.0

# 5. A2 parser 相容性檢查邏輯
grep -rn "template_version" app/oscal/service/excel_parser/ --include="*.py" | head -5
# → 確認對 v2.0.0 / v2.1.0 容錯處理

§2

任務清單

T1 — sheet_definitions.py ALL_SHEETS 加回 SHEET_LEVERAGED(BE)

檔案app/module_frame/excel_template/sheet_definitions.py:259

改動:對齊 design-C7.md §5.1(tuple 內加 SHEET_LEVERAGED 在 SHEET_INFO_SYSTEMS 後 / SHEET_CONTROLS 前)

附帶:移除 line 255-258 註解(解釋 v2.0.0 隱藏的歷史脈絡),改成 C7 註解說明恢復理由

Commit messagefeat(ssp-excel-template): C7 恢復 06_外部利用服務 sheet


T2 — parser.py 改回讀取(BE)

檔案app/oscal/service/excel_parser/parser.py:70

改動:對齊 design-C7.md §5.2(呼叫 sh.parse_leveraged_sheet

Commit message:合併到 T1 同個 commit(連動改動)


T3 — TEMPLATE_VERSION bump v2.0.0 → v2.1.0(BE)

檔案app/module_frame/excel_template/sheet_definitions.py(或對應位置)

改動

TEMPLATE_VERSION = "v2.1.0"   # C7 (2026-MM-DD): 恢復 06_外部利用服務 sheet

相容性檢查

  • A2 parser 對 v2.0.0 / v2.1.0 / v1.x 的處理邏輯(pre-flight Step 5 驗證)
  • 若 parser 對舊版本 strict reject → 改 lenient mode + WARN

Commit message:合併到 T1


T4 — Unit test:06 sheet 匯入流程(BE)

檔案tests/test_excel_template_generator_blank.py / test_excel_template_generator_filled.py

新測試 case

  • 樣板下載含 06 sheet(v2.1.0 generator 輸出)
  • 06 sheet 結構:3 欄 + header style + 黃底必填欄位

檔案tests/test_excel_parser.py

新測試 case

  • 餵一份 v2.1.0 樣板 → parser 回 ParsedExcel(leveraged=[...]) 非空
  • 餵一份 v2.0.0 舊樣板(無 06 sheet)→ parser 回 leveraged=[] 且 validation_errors 加 non-blocking warning
  • service_name 缺 → validation error

檔案tests/test_a4_write_strategy_leveraged.py 已存在,沿用

Commit messagetest(ssp-excel): C7 加 06_外部利用服務 sheet 匯入流程測試


T5 — Smoke test:下載 + 匯入 round-trip(manual)

步驟

  1. GET /api/1.0/module-frame/<uid>/ssp-import-template?mode=blank 下載樣板
  2. 開啟確認 06 sheet 存在、有 3 欄
  3. 手動填 2 筆 leveraged 資料
  4. 透過 SSP 匯入流程(A2 endpoint)上傳
  5. 確認 ssp_system_implementation_items 內有 implementation_type='leveraged-authorization' 對應 2 筆

SQL 驗證

SELECT name, title, purpose, implementation_type
  FROM oscal.ssp_system_implementation_items
 WHERE implementation_type = 'leveraged-authorization'
   AND scope_type = 'ssp'
   AND scope_id = <test_ssp_id>
 ORDER BY created_at DESC LIMIT 5;

T6 — Changelog

檔案docs/changelog/YYYY-MM-DD-feat-ssp-excel-leveraged-sheet-restore.md

---
type: feat
breaking: false
modules: [module_frame, oscal]
---

## 需求說明
C7:恢復 v2.0.0 隱藏的 06_外部利用服務 sheet。Phase C 走向 SSP 直接編輯後,
純文字輸入到 SSP 變得合理,重啟此 sheet 的匯入路徑。

## 變更範圍
### BE
- `app/module_frame/excel_template/sheet_definitions.py`:ALL_SHEETS 加回 SHEET_LEVERAGED
- `app/oscal/service/excel_parser/parser.py`:leveraged=[] 改回呼叫 parse_leveraged_sheet
- TEMPLATE_VERSION v2.0.0 → v2.1.0
- `tests/`:新增 06 sheet round-trip 測試

## 行為差異
- Excel 樣板下載多一頁 06_外部利用服務(3 欄純文字:service_name / provider / purpose)
- 匯入流程處理 06 sheet 資料 → ssp_system_implementation_items (type='leveraged-authorization')
- v2.0.0 舊樣板仍可匯入(向後相容,無 06 sheet 視為空)

§3

完成標準(DoD)


§4

風險 / Rollback

風險 緩解
v2.1.0 樣板 user 用舊 parser 匯入 break 已驗證 parser 對缺 sheet 是 non-blocking warning
LeveragedWriteStrategy 已 stale 不能用 A4 階段已有測試,無 stale 風險
寫入時撞 A5 bugfix「整份覆蓋」邏輯 此 fix 對 leveraged 已生效(write_strategy base.py)

Rollback:純樣板改動,git revert 即可。已匯入的 leveraged 資料維持在 SSP items 表內,不會被影響。