SSP docx 匯入 / 更新(Project SSP Docx Import)
功能群:合規框架與 SSP|匯入三步式先讀 _overview §4;共用精靈見 module-frame-import
事實基準:2026-07-05 從 FE / BE code 掃出;endpoint 對
routes.json、schema 對db_schema.json、error code 開檔驗
1. 功能描述
SSP docx 匯入 / 更新是把 docx 內容匯入更新某專案 living
SSP 的頁面。route
掛在專案下(/project/projects/:id/ssp-import-docx),但功能屬匯入家族——用與資源庫匯入相同的共用精靈
SspDocxImportPage.vue,以 mode='update-ssp' +
source_type='project_ssp' +
mode='statement_only' 參數化。走三步式(上傳 → 解決差異 →
預覽 / 確認),confirm 只寫控制實作的
statement(不動既有控制其他欄位),完成後導回專案規劃。
主要使用者:專案 SSP 維護者(規劃階段)。
角色速覽:專案 SSP 維護者(規劃階段 manager / 有編輯權者,見 專案規劃頁 §3)。
歸屬註:本頁 route 在 project 下,但功能上屬於「匯入」這個家族(與 module-frame-import 共用同一套精靈),因此文件歸類在合規框架與 SSP 群;若日後重整可考慮移專案管理群。
1.1 功能總覽(本頁全部功能)
| # | 功能 | 說明 | 位置 | 詳述 |
|---|---|---|---|---|
| 1 | 上傳 docx | .docx 拖放上傳解析 | Step1 | UC-SSI-01 |
| 2 | 解決差異 | match / append / skip 決策 | Step2 | §12 |
| 3 | 預覽 / 確認 | 分節 tab(控制實作為主)內嵌決策 | Step3 | §6.2 |
| 4 | statement_only 寫入 | confirm 只更新控制實作 statement | 確認 | §12 |
| 5 | 丟棄 | DELETE parse job | Step1/2/3 | UC-SSI-02 |
| 6 | 導回規劃 | confirm 後帶 ?return_to=ssp 回專案規劃 |
完成 | §10 |
UC(§2)展開本頁具實質後端邏輯的功能:三步匯入含 confirm 決策驗證閘(UC-SSI-01,涵蓋上傳解析 1 / 解決差異 2 / 預覽確認 3 / statement_only 寫入 4)、丟棄暫存解析 job(UC-SSI-02)。導回規劃(6)為純導覽,見 §10。
2. Use Case
角色速覽:專案 SSP 維護者(規劃階段 manager / 有編輯權者,見 專案規劃頁 §3)。
流程圖視覺慣例:菱形 = 判斷、橘底 = 例外 / 擋下、紅框 = 錯誤(標 error code)、綠框 = 成功終點、虛線 = 可選路徑。
UC-SSI-01 從 docx 匯入更新專案 SSP
| 項目 | 內容 |
|---|---|
| 角色 | 專案 SSP 維護者 |
| 前置條件 | 已登入;專案有 living SSP(sspUid) |
| 產出 / 後置條件 | confirm 只更新控制實作 statement;導回規劃 |
UC-SSI-02 丟棄解析 job
| 項目 | 內容 |
|---|---|
| 角色 | 專案 SSP 維護者 |
| 前置條件 | 精靈任一步(Step1 / 2 / 3)已有解析
job(parse_uid) |
| 產出 / 後置條件 | 刪除暫存解析 job;living SSP 未變動;解析 job 不存在 →
GRC_DOCX_PARSE_JOB_NOT_FOUND(404023) |
3. 權限矩陣
| 操作 | FE 判定 | BE 強制 | BE 檢查位置 |
|---|---|---|---|
| 進頁 / 上傳 / confirm | 專案編輯權(規劃階段) | @jwt_required() + 專案權限(require_manager per
project_planning auth) |
api/oscal/routes/ssp/ssp_docx_import_route.py |
權限比照專案規劃頁的 SSP 寫入(見 專案規劃頁 §3);docx 匯入路徑是否同等 phase / 角色檢查需個案確認(規劃頁 §12 坑 7 同款注意)。
4. 狀態機與前置條件
匯入三步式見 _overview §4。error code(docx 系):
| 條件 | 效果 | 出處 |
|---|---|---|
| 檔非 .docx / 超 10MB | GRC_DOCX_INVALID_FILE(400005)/
_FILE_TOO_LARGE(400006) |
grc_error_code.py:156-157 |
| source_type 非法 | GRC_DOCX_SOURCE_TYPE_INVALID(400008,只允 project_ssp
/ module_frame) |
:159 |
| 缺 framework 參數 | GRC_DOCX_FRAMEWORK_REQUIRED(400007) |
:158 |
| decisions 缺漏 / 未知 control_id / party_uid | GRC_DOCX_DECISIONS_INCOMPLETE(400013)/
_INVALID_CONTROL_ID(400022)/
_INVALID_PARTY_UID(400023) |
:162-164 |
| 來源 / 解析 job 不存在 | GRC_DOCX_SOURCE_NOT_FOUND(404022)/
_PARSE_JOB_NOT_FOUND(404023) |
:193-194 |
5. UI 設計
版面骨架:與資源庫 docx 精靈相同(共用
SspDocxImportPage),見 module-frame-import §5——差異僅
mode='update-ssp' / source_type='project_ssp'
/ statement_only。
實機截圖(STG,亮色模式,2026-07-06,帳號 blsadmin):

② 解決差異、③ 預覽 / 確認兩張截圖從缺:需實際上傳 docx 觸發解析 job 才能進入後續步驟,屬寫入動作(會在 STG 建立 parse job / 暫存資料),不在本次唯讀截圖範圍內;待專案安排實測資料時再補。
狀態呈現:三步(上傳 / 解決差異 / 預覽);決策持久化 Pinia +
localStorage;confirm 導回規劃帶 ?return_to=ssp /
?project_uid / ?ap_uid。
6. API 規格
Envelope:成功 {"status": true, "data": …}、失敗
{"error_code": "…", "msg": "…"}。
6.1 總清單(本頁呼叫的全部 endpoint)
| 分類 | Method + Path | 說明 | 完整規格 |
|---|---|---|---|
| docx 解析 | POST /ssp-docx-imports/parse |
上傳解析(source_type=project_ssp, mode=statement_only) | §6.2 |
| docx 預覽 / 確認 / 丟棄 | GET /ssp-docx-import/{parse_uid}、POST
.../confirm、DELETE .../{parse_uid} |
三步式 | §6.2 |
| SSP 控制實作匯入 | POST
/ssp/{ssp_uid}/control-implementations/import[/validate,/confirm] |
控制實作 Excel 匯入三步(規劃頁批次維護亦用) | GAI-SD-02 |
| 樣板 | GET /ssp-import-template |
下載 SSP 匯入樣板 | GAI-SD-02 |
6.2 核心 endpoint
[POST] /ssp-docx-imports/parse
Request(multipart):
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
file |
raw | 否 | .docx 檔 |
source_type |
string | 否 | 固定 project_ssp |
source_uid |
string | 否 | ssp_uid |
mode |
string | 否 | 固定 statement_only |
framework |
string | 否 | — |
Response
data:{parse_uid, status}。出處:api/oscal/routes/ssp/ssp_docx_import_route.py::SspDocxImportParseRoute
[GET] /ssp-docx-import/{parse_uid} ・ [POST] .../confirm
GET 回 {status, parsed_result};confirm body
decisions[] / overrides →
只更新控制實作
statement(statement_only:不動既有控制其他欄位)。出處:app/oscal/service/ssp_docx_import_app_service.py
7. 前端檔案地圖(compliance-manager-fe/)
| 檔案 | 角色 |
|---|---|
src/views/project/ImportDocxPage.vue |
wrapper(mode=update-ssp;props: sspUid / project_id / framework) |
src/components/grc/ssp-docx-import-v2/SspDocxImportPage.vue |
共用 docx 精靈元件(同 module-frame-import) |
src/config/router/index.js:792-796 |
route
project-ssp-import-docx(/project/projects/:id/ssp-import-docx) |
src/config/api/api.js |
endpoint 常數 |
8. 後端檔案地圖(本頁核心鏈路)
| 鏈路 | Route | App Service | 底層 |
|---|---|---|---|
| docx 解析 / confirm | api/oscal/routes/ssp/ssp_docx_import_route.py(source_type=project_ssp) |
app/oscal/service/ssp_docx_import_app_service.py(statement_only
confirm) |
oscal.ssp_docx_parse_jobs → 專案 living SSP |
DDD 提醒:與資源庫 docx 匯入共用 route / service,靠
source_type 分流;statement_only 只寫
statement。
9. DB
9.1 資料表總清單
| 表 | 讀/寫 | 說明 | 欄位詳述 |
|---|---|---|---|
| oscal.ssp_docx_parse_jobs | 寫(暫存) | docx 解析暫存 job(source_type=project_ssp) | module-frame-import §9.3 |
| oscal.system_security_plans | 讀 | 目標 living SSP | GAI-SD-03 |
| oscal.ssp_statements | 寫(confirm) | 控制實作 statement(statement_only) | 規劃頁 §9.3 |
| oscal.ssp_implemented_requirements | 讀 / 寫 | 控制實作(依 decisions match/append) | 規劃頁 §9.3 |
| oscal.parties | 寫(decisions 含 party) | 人員(如 docx 帶 parties) | GAI-SD-03 |
9.2 ER 圖
SSP 子表結構見 規劃頁
§9.2;本頁寫暫存 ssp_docx_parse_jobs(confirm 後只落地
statement)。
9.3 核心表
oscal.ssp_docx_parse_jobs 結構見 module-frame-import
§9.3(共用暫存表,source_type=project_ssp 區分)。
10. 頁面邏輯與資料對應
載入 / 儲存流程:進頁 → 上傳
parse(source_type=project_ssp)→ 解決差異 → 預覽 →
confirm(statement_only)→ 導回規劃(?return_to=ssp)。
關鍵欄位對應:
| 畫面元素 | API 欄位 |
|---|---|
| 差異決策 | confirm decisions[](match/append/skip) |
| 控制實作 statement | confirm 只更新 statement(不動其他欄位) |
錯誤對應:見 §4 error code 表。
11. 背景行為與外部依賴
| 類型 | 內容 |
|---|---|
| 解析 | docx 解析成暫存 job;confirm 只寫 statement |
| Socket | 本頁無 socket |
| jedi-* 套件 | jedi-oscal-v2(SSP 解析寫入) |
| 系統參數 | 無 feature flag |
12. 邊界情況與已知坑
- 共用精靈 source_type 分流:與 module-frame-import 共用
SspDocxImportPage與 route / service,靠source_type=project_ssp走 SSP 路徑;改共用元件 / service 兩頁都受影響 - statement_only 只寫 statement:confirm
只更新控制實作的 statement,不動既有控制其他欄位(與資源庫
mode=full寫全欄位不同)——避免覆蓋專案已填的實作狀態 - 權限比照規劃頁 SSP 寫入:docx 匯入是否同等 phase / 角色檢查需個案確認(同規劃頁 §12 坑 7)
- decisions 必完整:所有匹配控制項要做選擇(否則
GRC_400013);未知 control_id / party_uid 擋(400022/400023) - 導回帶 context:confirm 後
?return_to=ssp/?project_uid/?ap_uid帶回規劃頁上下文
13. 開發與驗證
- 跑起來:BE
python main_socketio.py(port 8000,log 在log/app.log);FE Vite dev server。BE 改 service code 必重啟 - 測試帳號:專案 SSP 維護者(規劃階段
manager);密碼見
.env/ 部署文件 - 導航路徑:專案規劃 / 總覽 → SSP docx
匯入(
/project/projects/:id/ssp-import-docx) - 前置資料:專案有 living SSP;一份 docx 檔
- E2E:
compliance-manager-test/repo;以SSP 匯入/ssp-import-docx搜尋 - 相關文件:共用精靈 module-frame-import、專案規劃頁 project-planning、匯入三步式
_overview §4;SSP 匯入匯出 Phase 2 見 memory
project_ssp_import_export_phase2