系統安全計畫編輯器(SSP Editor)
功能群:專案管理|狀態機與共用概念先讀 功能群總覽;OSCAL SSP 領域概念見 oscal-knowledge
事實基準:2026-07-06 從 FE / BE code 掃出;表結構對
db_schema.json、endpoint 對routes.json逐條核
1. 功能描述
系統安全計畫編輯器是專案 living SSP
的內容編制面板:受評方在此填寫 OSCAL System Security Plan
的各部分——系統特性(system-characteristics)、參與單位 /
人員(parties)、系統實作的元件(components)、利用授權(leveraged
authorizations)、資產清冊(inventory-items)。這是 專案規劃頁 的
Tab1「系統安全計畫」 內容(面板
SspTabPanel.vue);控制項 / AO
的實作現況(control-implementation)不在本頁,那是規劃頁 Tab0 的事(見
規劃頁 UC-PP-01)。
與規劃頁 Tab0 共用同一組可編輯 gate:只有 AP =
planning 且使用者為專案 manager
時可寫;launch-audit 後 living SSP
凍結成快照,全面唯讀。
主要使用者:專案 manager(寫)、專案任一參與者(讀)。
角色速覽(完整定義見 _overview §3):
| 角色 | 一句話 |
|---|---|
| manager | 專案經理 — 唯一能編輯 SSP 各部分者(且需 AP = planning) |
| 參與者 | auditor / reviewer / viewer — 可讀不可寫 |
1.1 功能總覽(本頁全部功能)
本頁是 hub(概覽 + 共用 gate + Excel 跨子區流程):五個子區各自的 field-level 逐欄規格(表單每欄 / 逐支 API request-response / DB jsonb 結構 / 逐坑)拆成獨立子頁,見「詳述」欄連結。
| # | 功能 | 說明 | 位置 | 詳述(field-level 子頁) |
|---|---|---|---|---|
| 1 | 基本資料編輯 | 系統名稱 / 描述 / 敏感度 / 狀態 / owner / 授權邊界等(system-characteristics,1:1 upsert,8 欄) | 子 Tab 基本資料 | 基本資料 |
| 2 | 參與單位管理 | organization 型 party 的增改刪(DataTable + Dialog,含計數) | 子 Tab 單位 | 參與方 |
| 3 | 參與人員管理 | person 型 party 的增改刪 | 子 Tab 參與人員 | 參與方 |
| 4 | 元件清冊 | system-implementation 元件增改刪(type 15 enum、protocol、port 等 9 欄) | 子 Tab 元件·授權·資產 › 元件 | 元件清冊 |
| 5 | 利用授權 | leveraged authorization 增改刪(title / provider / 授權日 / 類別 / 狀態) | 同上 › 授權 | 利用授權 |
| 6 | 資產清冊 | inventory-items 增改刪;依 asset_type 分「設備資產 / 系統資產」兩表 | 同上 › 資產 | 資產清冊 |
| 7 | SSP Excel 匯出 | 下載範本(空表 blank / 帶現況 filled) | TabView 右上「下載範本」 | UC-SE-02 |
| 8 | SSP Excel 匯入 | 上傳 .xlsx 解析 → 跳共用預覽頁 → confirm 批次寫入 | TabView 右上「匯入」 | UC-SE-02 |
| 9 | 唯讀 / 無 SSP 提示 | 無 sspUid → 提示先啟動稽核計畫;AP 凍結 / 非 manager → 唯讀警告 | 上層 Message | §4 |
UC(§2)展開兩條核心路徑:各子區共同的內容編輯守門 UC-SE-01(五類 CRUD 的共同 gate 與 M2M 坑總覽,逐欄細節見各子頁)、Excel 批次匯入匯出 UC-SE-02(跨五子區、留在 hub);唯讀 / 提示屬狀態呈現見 §4 / §5。控制項 / AO 現況(control-implementation)與程序書關聯不在本頁,見 規劃頁 Tab0。
2. Use Case
角色速覽(同 §1):
| 角色 | 一句話 |
|---|---|
| manager | 專案經理 — 唯一能編輯者(需 AP = planning) |
| 參與者 | auditor / reviewer / viewer — 可讀不可寫 |
流程圖視覺慣例:菱形 = 判斷、橘底 = 例外 / 擋下、紅框 = 錯誤(標 error code)、綠框 = 成功終點、虛線 = 可選路徑。
UC-SE-01 編輯 SSP 各部分(系統特性 / 單位 / 人員 / 元件 / 授權 / 資產)
| 項目 | 內容 |
|---|---|
| 角色 | 專案 manager(讀:任一參與者) |
| 前置條件 | 已載入 living SSP(sspUid);AP =
planning(否則唯讀) |
| 產出 / 後置條件 | 對應 oscal.ssp_* 表 upsert / insert / delete;基本資料
1:1,其餘為清單項;面板計數徽章更新 |
UC-SE-02 SSP Excel 批次匯出 / 匯入
| 項目 | 內容 |
|---|---|
| 角色 | 專案 manager |
| 前置條件 | AP = planning(匯入鈕 canEdit
才顯示) |
| 產出 / 後置條件 | 匯出 = 下載 xlsx 範本;匯入 = 解析後跳共用預覽頁,confirm 才批次寫入 SSP 各子表 |
3. 權限矩陣
| 操作 | FE 判定 | BE 強制 | BE 檢查位置 |
|---|---|---|---|
| 讀各子區 | 參與者即可 | require_participant(SSP → project → 任一
participant) |
common/middleware/permission/ssp_permission.py |
| 編輯任一子區(POST/PUT/DELETE) | canEdit = apStatus==='planning' 且
currentUserRole==='manager' |
require_manager = manager 角色 + AP 可編輯 |
各 service(如
app/oscal/service/ssp_components_service.py,require_manager
@ :63) |
| Excel 匯入 confirm | 同上 | require_manager |
app/oscal/service/ssp_excel_import_app_service.py(confirm
:124-125) |
⚠️ 部分 SSP endpoint(如 system-characteristic)route 層僅
@jwt_required(),實際角色守門在 service 層——與本群其他頁一致(讀require_participant/ 寫require_manager)。改權限以 service 層檢查為準。
4. 狀態機與前置條件
本頁無獨立狀態機,承接 living SSP 的可編輯 gate(與 規劃頁 §4 同源):
| 條件 | 效果 | 出處 |
|---|---|---|
!sspUid |
上層 Message「請先啟動稽核計畫,再回來編輯 SSP」 | SspTabPanel.vue(readonlyHint,:88-98) |
apStatus === 'planning' 且 role=manager |
canEdit=true:各子區可增改刪 |
同檔 :84-86 |
apStatus !== 'planning'(含 closed) |
living SSP 凍結為快照,全面唯讀 | 同上 |
| 非 manager | 唯讀警告 | 同上 |
5. UI 設計
📸 實際畫面截圖待補(一律亮色模式拍攝):預計補 SSP 編輯器整頁(四子 Tab)
sspedit-overview.png、元件/授權/資產子區sspedit-components.png、Excel 匯入 Dialogsspedit-excel.png。
版面骨架與子區職責(本頁為 hub:四子 Tab 分屬五個 field-level 子頁,Excel 匯入跨子區留在 hub;彩色區塊可點跳對應子頁,API 僅標代表性):
狀態呈現:子 Tab header 帶計數徽章(由各子面板
emit);SECTION_TAB_MAP 支援
?section=<key> 深連結(舊 key
scope/scope_devices/scope_info_systems/leveraged
自動 redirect 到整合後的元件·授權·資產 tab,維持書籤相容);無
socket,寫入後前端本地更新 + 重載。
6. API 規格
Envelope:成功 {"status": true, "data": …}、失敗
{"error_code": "…", "msg": "…"}。
6.1 總清單(本頁呼叫的全部 endpoint)
| 分類 | Method + Path | 說明 | 完整規格 |
|---|---|---|---|
| 基本資料 | GET / PUT /ssp/{ssp_uid}/system-characteristic |
系統特性讀取 / 儲存(1:1 upsert,8 欄) | 基本資料 §6 |
| 單位 / 人員 | GET / POST /ssp/{ssp_uid}/parties、PUT / DELETE
.../parties/{party_uid} |
party 增改刪(organization / person 依 type 過濾) |
參與方 §6 |
| 元件 | GET / POST /ssp/{ssp_uid}/components、PUT / DELETE
.../components/{uid} |
元件清冊增改刪 | 元件清冊 §6 |
| 授權 | GET / POST /ssp/{ssp_uid}/leveraged、PUT / DELETE
.../leveraged/{uid} |
利用授權增改刪 | 利用授權 §6 |
| 資產 | GET / POST /ssp/{ssp_uid}/inventory-items、PUT / DELETE
.../inventory-items/{uid} |
資產清冊增改刪 | 資產清冊 §6 |
| Excel | GET
/ssp/{ssp_uid}/excel-template?mode=blank|filled |
下載匯入範本 | GAI-SD-02 |
| Excel | POST /ssp/{ssp_uid}/excel-import/upload →
/{parse_uid} → /confirm |
匯入解析 → 預覽 → 批次寫入(三步式) | §6.2 |
五個子區的逐欄 request / response 表在各自子頁 §6;以下 §6.2 只留跨子區的 Excel 匯入(本 hub 專屬)。
6.2 核心 endpoint(跨子區)
[POST] /ssp/{ssp_uid}/excel-import/upload
上傳 .xlsx 解析(source_type='ssp',
source_uid=ssp_uid),成功後 FE 跳轉共用預覽頁(route
module-frame-import-excel-preview),走與範本匯入相同的
parse → preview → confirm
三步式管線。出處:api/oscal/routes/ssp/ssp_scoped_excel_import_route.py:32-68、app/oscal/service/ssp_excel_import_app_service.py
7. 前端檔案地圖(compliance-manager-fe/)
| 檔案 | 角色 |
|---|---|
src/components/grc/ssp/SspTabPanel.vue |
本面板(四子 Tab 容器 + Excel 動作) |
src/components/grc/ssp/SspBasicSection.vue |
子 Tab 基本資料 |
src/components/grc/ModuleFramePartiesPanel.vue |
子 Tab 單位 / 參與人員(party-type 過濾;SSP
與範本共用) |
src/components/grc/ssp/SspComponentsLeveragedInventoryTab.vue |
子 Tab 元件 · 授權 · 資產 |
src/views/project/ProjectPlanningView.vue |
掛載點:規劃頁 Tab1 |
src/service/SspService.js |
各子資源 CRUD service |
src/service/SspExcelImportService.js |
Excel 匯入(uploadSspScoped) |
src/stores/menuStore.ts |
sspPartyRoleMenu(party role dropdown 來源) |
8. 後端檔案地圖(本頁核心鏈路)
| 鏈路 | Route | App Service | 底層 |
|---|---|---|---|
| 系統特性 | api/oscal/routes/ssp/ssp_system_characteristic_route.py |
SspSystemCharacteristicAppService |
oscal.ssp_system_characteristics(1:1) |
| party | api/oscal/routes/ssp/ssp_party_route.py |
SspPartyAppService |
oscal.parties(透過 SSP metadata_id
掛接) |
| 元件 / 授權 / 資產 | ssp_components_route.py /
ssp_leveraged_route.py /
ssp_inventory_items_route.py |
SspComponentsAppService
等(require_participant 讀 / require_manager
寫) |
ssp_system_implementations containment → 三張子表 |
| Excel 匯入 | ssp_scoped_excel_import_route.py |
SspExcelImportAppService(parse /
confirm,共用範本匯入管線) |
parse job 暫存 → 批次寫各子表 |
9. DB
9.1 資料表總清單(本頁讀寫的全部表)
| 表 | 讀寫 | 說明 | 詳述 |
|---|---|---|---|
| oscal.system_security_plans | 讀 | SSP 主檔(uuid / metadata_id / status) | §9.3 |
| oscal.ssp_system_characteristics | 讀 / 寫 | 系統特性(1:1) | §9.3 |
| oscal.ssp_system_implementations | 讀 | 元件 / 授權 / 資產的 containment 父 | GAI-SD-03 |
| oscal.ssp_components | 讀 / 寫 | 系統元件清冊 | §9.3 |
| oscal.ssp_leveraged_authorizations | 讀 / 寫 | 利用授權 | §9.3 |
| oscal.ssp_inventory_items | 讀 / 寫 | 資產清冊(設備 / 系統) | §9.3 |
| oscal.parties | 讀 / 寫 | 參與單位 / 人員(透過 SSP metadata 掛接) | §9.3 |
9.2 ER 圖(本頁讀寫範圍)
9.3 核心表欄位
各子表的完整欄位卡(含 DB comment、jsonb 內部結構、props 保留鍵)在各子頁 §9.3:
| 表 | 逐欄詳述 |
|---|---|
| oscal.ssp_system_characteristics | 基本資料 §9.3 |
| oscal.parties | 參與方 §9.3 |
| oscal.ssp_components | 元件清冊 §9.3 |
| oscal.ssp_leveraged_authorizations | 利用授權 §9.3 |
| oscal.ssp_inventory_items | 資產清冊 §9.3 |
共通提醒:五張子表的產品擴充欄一律走各自
propsjsonb([{name,value}])而非 OSCAL 核心欄;party_uuid/component-uuid等跨表關聯皆軟式參照(無 FK)。細節見各子頁。
10. 頁面邏輯與資料對應
各子面板獨立 GET 載入(useSspSystemCharacteristic /
useSspParties / useSspLeveraged 等 composable
包裝 cache)。
| 畫面元素 | FE state / composable | API 欄位 |
|---|---|---|
| 基本資料表單 | useSspSystemCharacteristic |
system-characteristic 各欄 |
| 單位 / 人員 DataTable | useSspParties(load/invalidate) |
parties[](type 過濾) |
| party role dropdown | menuStore.sspPartyRoleMenu |
9 個 C1 master role |
| 元件 / 授權 / 資產清單 | 各自 GET | components / leveraged / inventory-items |
儲存流程:基本資料 = PUT 1:1;清單項 =
POST/PUT/DELETE 單筆 → 對應 composable invalidate →
重載。Deep link:?section=<key>
進頁自動切子 Tab。
11. 背景行為與外部依賴
| 類型 | 內容 |
|---|---|
| socket | 無(寫入後本地更新 + 重載) |
| store | menuStore.sspPartyRoleMenu(party role master
data,一次性 cache) |
| 共用管線 | Excel 匯入跳共用預覽頁(與範本匯入
module-frame-import-excel-preview 同一頁),走 parse →
preview → confirm 三步式 |
| 凍結 | launch-audit 後 living SSP
凍結成該輪快照(round.ssp_id),本頁轉唯讀(見 _overview §4) |
12. 邊界情況與已知坑
- 資產
implemented_components是 M2M,PUT 改不了:BE update path 受 FK 限制無法改資產與元件的多對多關聯;FE 在編輯既有資產時 disable 該欄並提示「需 delete + 重建」,新增時可正常填。 - 資產分流(FR-032):
asset_type='information_system'→ 系統資產(infoSystemOptions picker);其餘 / 預設 → 設備資產(deviceOptions picker)——同一inventory-items表、UI 分兩張。 - party 無獨立 mapping 表:單位 / 人員掛在 SSP 的
metadata(parties.metadata_id),type分 person / organization;授權 / 資產以party_uuid軟式參照(無 FK),刪 party 前留意被參照。 - 舊 section key
相容:
?section=scope/scope_devices/scope_info_systems/leveraged會 redirect 到整合後的「元件·授權·資產」子 Tab(Phase 4 L3 清理併 tab,書籤仍可用)。 - SSP 寫入無 phase guard(BE):唯讀是 FE 鎖的,凍結後直接打 API 仍會改 living SSP——同 規劃頁 §12 坑 3。
- 無 socket:多人同編互不可見,後儲存者覆蓋。
13. 開發與驗證
- 跑起來:起 BE + FE;登入見
.env/ 部署文件測試帳號(需該專案 manager) - 導航:專案規劃頁 →
Tab1「系統安全計畫」(
/project/projects/:id/planning?tab=1);或帶?section=<key>深連結 - 前置資料:需一個有 living SSP 的專案(AP = planning);建幾筆元件 / 授權 / 資產測 CRUD 與 M2M 坑;下載 filled 範本測 Excel round-trip
- 相關:控制項 / AO 現況見 規劃頁 UC-PP-01;OSCAL SSP 領域概念見 oscal-knowledge skill;Excel 匯入共用管線見 範本匯入