user 要的是給新人開發 / 追蹤用的「詳細規格書」,不是概覽。核心原則(user 原話):
「你都用 CRUD 帶過,但是要 CRUD 到哪裡、用哪些 API、畫面欄位是怎樣,都沒寫工程師怎麼開發?怎麼追蹤?這是一份詳細規格書,希望得到詳細的參考資訊,而不是敷衍帶過。」
所以每個功能要到 field-level:每個畫面欄位(label / 型別 / 必填 / 列舉值 / disabled 條件 / 存哪個 DB 欄或 props 鍵)、每支 API(method + path + 逐欄 request/response 表)、每個 error code、DB jsonb 內部結構。「CRUD 帶過」「指向 GAI-SD-02」= 不合格。
合格範本已寫好 → 讀 docs/specs/v1.8.0/project-management/project-ssp-inventory.md(資產頁,§5 逐欄表單 / §6 完整 request-response 欄位表 / §9 jsonb 結構 / §12 逐坑)。
/parties API 只差 type 過濾,合一頁避免重複 drift。scripts/deliverables/out/db_schema.json(不是 docs/system-design/.../tbls/*.md,那份會 drift,本 session 已踩到:元件 tbls 版寫 ssp_id/component_type/leveraged_authorization_uid 欄,db_schema.json 才是 system_implementation_id/uuid/type,且 leveraged_authorization_uid 在 props 不是欄位)。html/ 依規則先不 commit。writing-feature-specs(13 節模板 + 事實來源紀律 + build 驗證)。本 session 是「FR-047 手冊可讀性/詳細化」大 arc,做了六大塊(詳見對應頁):
project-settings.md 刪除(route 已孤兒,內容併入規劃頁);基本資訊/參與人員 → 規劃頁 UC-PP-09(含 ⚠️ PUT /grc/project 無角色守門安全 finding 搬進 §12 坑 11);cloud-integrations.md 5 處「專案設定頁」措辭修正。evidence/document-pool.md(程序書池,Tab4)、evidence/project-cloud-integration.md(專案雲端 verify-repair,Tab5)、project-management/project-ssp-edit.md(SSP 編輯器 hub,Tab1)。project-ap-list(稽核輪次清單)移到 project-overview 前(照下鑽動線);規劃頁 §5 加「六個 Tab 對照表」(每 Tab 指向真頁,0 死指標)。project-ssp-inventory.md 已寫完驗證;其餘 4 頁待寫(見待辦 A)。驗證狀態:全部 build ✅(58 頁)、自查敏感資訊/「GRC 系統」= 0、新圖 error code 逐一比對防杜撰、斷圖 0。
範本 = project-ssp-inventory.md(已寫好的第 5 頁)。放 docs/specs/v1.8.0/project-management/:
| 待寫頁 | 實體 / API | FE 元件 |
|---|---|---|
| project-ssp-basic.md | 系統特性 /system-characteristic |
SspBasicSection.vue |
| project-ssp-parties.md | 參與方 /parties(單位+人員合一) |
ModuleFramePartiesPanel.vue |
| project-ssp-components.md | 元件 /components |
SspComponentsLeveragedInventoryTab.vue |
| project-ssp-leveraged.md | 利用授權 /leveraged |
同上 |
已驗證 facts(本 session 5 隻 Explore agent 掃出 + 對 db_schema.json/routes.json/BE code 核過,直接用不必重跑):
共用(4 頁都適用):
require_participant(讀)/ require_manager(寫 = manager + AP=planning)。碼:GRC_403051(GRC_NOT_PROJECT_MANAGER)、GRC_412028(GRC_SSP_EDIT_AP_NOT_ACTIVE,AP 關閉/封存)。canEdit = apStatus==='planning' && role==='manager';launch-audit 後 living SSP 凍結唯讀。/ssp/{ssp_uid}/...(已驗 routes.json 存在);表全在 oscal schema(已驗 db_schema.json)。apiBase 切 ssp vs module-frame;共用 ModuleFrame*Service mapper;props jsonb = [{name,value}] 非破壞性合併;無 socket;composable cache(useSsp*)。① project-ssp-basic(系統特性,1:1 upsert)
/ssp/{uid}/system-characteristic。name(範圍名稱,InputText,必填→system_name) / system_identifier(範圍識別碼→system_ids[0].id jsonb) / security_sensitivity_level(安全分類等級,Dropdown low·moderate·high,預設 high) / target_type(範圍類型→props[target-type]) / status(運行狀態,Dropdown active·under-development·disposition·other——FE 只 4 種,DB status_state 有 5 種缺 under-major-modification) / owner_uid(範圍負責人,Dropdown searchable userMenu→props[owner-uid]) / scope_description(授權邊界描述,Textarea→authorization_boundary_description) / description(描述,Textarea)。SspSystemCharacteristicUpdateSchema(全欄 allow_none,route strip None)/ SspSystemCharacteristicResponseSchema。oscal.ssp_system_characteristics(ssp_id UNIQUE 1:1):system_name/system_name_short/description/security_sensitivity_level/date_authorized/system_ids(jsonb)/status_state(varchar40)/status_remarks/authorization_boundary_description/authorization_boundary_props(jsonb)/props(jsonb: target-type + owner-uid)。api/oscal/routes/ssp/ssp_system_characteristic_route.py、serializer api/oscal/serializers/ssp/ssp_system_characteristic_inproject.py、service app/oscal/service/ssp_system_characteristic_app_service.py、mapper app/module_frame/service/module_frame_system_characteristic_service.py。② project-ssp-parties(參與方,單位+人員合一頁)
/ssp/{uid}/parties、PUT/DELETE .../parties/{party_uuid};party-type prop = organization / person 過濾。matched_user_id/matched_org_unit_id(鉤稽,Dropdown person→userMenu·org→orgUnitMenu,選填) / role(Dropdown 9 OSCAL role,必填,預設 person=system-owner·org=responsible-organization) / name(必填,編輯時 disabled 自然鍵) / email_address/telephone_number/address(選填)。scripts/sql/2026-05-22-seed-oscal-ssp-roles.sql):responsible-organization / system-owner / system-security-officer / authorizing-official / information-owner / information-provider / information-receiver / prepared-by / prepared-for。Menu:GET /system/menu/ssp_party_role。SspPartyUpsertSchema(party_type OneOf person·organization / name / role / title / email_address / telephone_number / address / matched_user_id / matched_org_unit_id);Response 多 enrich:matched_user_uid / matched_user_name / matched_org_unit_name。oscal.parties:metadata_id / uuid / type / name / short_name / email_addresses(text[]) / telephone_numbers(jsonb) / addresses(jsonb) / props(jsonb: role+title+telephone+address+matched_*)。GRC_400014(INVALID_PARTY_TYPE) / GRC_400015(PARTY_NAME_REQUIRED) / GRC_400016(PARTY_ROLE_REQUIRED) / GRC_404024(PARTY_NOT_FOUND) / GRC_403051 / GRC_412028。ap_task_participants + ssp_leveraged_authorizations 軟參照(無 FK),刪 party 無保護(follow-up)。api/oscal/routes/ssp/ssp_party_route.py、api/oscal/serializers/ssp/ssp_party.py、app/module_frame/service/module_frame_party_service.py。③ project-ssp-components(元件)
/ssp/{uid}/components、PUT/DELETE .../{item_uid}。title(名稱,必填) / component_type(類型,Dropdown 15 項,預設 system/BE 預設 software) / description(Textarea) / purpose(Textarea) / status(Dropdown 5:operational·under-development·under-major-modification·disposition·other) / leveraged_authorization_uid(Dropdown 來源 GET /leveraged) / protocol·port_ranges·security_auth(InputText→props)。oscal.ssp_components = system_implementation_id / uuid / type / title / description / purpose / status_state / status_remarks / responsible_roles(jsonb) / protocols(jsonb) / props(jsonb: protocol+port_ranges+security_auth+leveraged-authorization-uid) / links。無 leveraged_authorization_uid 欄(在 props)、無 tenant_id/is_active。GRC_404034(SSP_RESOURCE_NOT_FOUND) / GRC_403051。坑:component uuid 被 inventory implemented_components 軟參照。api/oscal/routes/ssp/ssp_components_route.py、app/oscal/service/ssp_components_app_service.py、mapper app/module_frame/service/module_frame_components_service.py。④ project-ssp-leveraged(利用授權)
/ssp/{uid}/leveraged、PUT/DELETE .../{item_uid};FE service 帶 'ssp' apiBase。title(授權名稱,必填) / provider(提供者) / date_authorized(Calendar,FE null→BE date.today()) / description(Textarea) / purpose(Textarea) / category(Dropdown 4:leveraged-authorization·external-service·interconnection·other,預設 leveraged-authorization) / status(Dropdown 5 同元件)。⚠️ Dialog 無 party_uuid 欄(硬置 null,註「日後 party picker UX」)。oscal.ssp_leveraged_authorizations:system_implementation_id / uuid / title / party_uuid(NN,null 時存 NIL-UUID 哨兵 00000000-...,軟參照 parties.uuid) / date_authorized / props / links / remarks。api/oscal/routes/ssp/ssp_leveraged_route.py、app/oscal/service/ssp_leveraged_app_service.py、mapper app/module_frame/service/module_frame_leveraged_service.py。寫完 4 頁後的收口:
project-ssp-edit.md 從「完整頁」改成 hub:§1.1 各子區「詳述」欄改指這 5 個子頁;§6/§9 的詳細內容可精簡成「見各子頁」(保留概覽 + Excel 匯入那條跨子區的留 hub)。scripts/deliverables/render_html.py):把 5 子頁巢狀在 project-ssp-edit.md 下(現在 project-ssp-edit 已巢狀在 project-planning 下,改成兩層:planning →[ssp-edit →[basic,parties,components,leveraged,inventory]],或平掛 project-management 群,擇一)。規劃頁 17 項裡「有真表單、卻只到 UC 流程圖級」的 5 項,要補逐欄 field-level。方法同 A(先 Explore 掃 FE 表單欄位 + BE serializer + db_schema,再親自寫):
| 功能 | 現況 | 要補 | 主 FE 元件 / endpoint |
|---|---|---|---|
| 4 任務檢視與編輯 ← 最大、最像「CRUD 帶過」 | UC-PP-02 流程 | 拆獨立子頁(建議 project-task-edit.md):任務表單逐欄(名稱/描述/指南/類型 general·survey/指派人員/部門/設備/問卷+審核人)+ full-replace 語意 + 關聯四表 |
ProjectPlanningView AO 面板 / 任務卡;PUT /grc/project/{uid}/job/{jobId} |
| 1 控制項/AO 現況編輯 | UC-PP-01 流程 | 補 field 表:implementation_status(5 種列舉)+ implementation_description + AO 備註 | PUT /ssp/{uid}/control-implementation/{cid}、.../objective/{stmtId} |
| 13 群組/控制項參與人員 | UC-PP-08 流程 | 補 field 表 + endpoint 逐欄 | POST/PUT/DELETE /control-group-participant、/project-control-participant |
| 15 專案基本資訊 | UC-PP-09 | 補 field 表(PUT /grc/project 欄位,可參 project-list.md §6.3 已有的 PUT 表) | PUT /grc/project/{uid} |
| 16 專案參與人員 | UC-PP-09 | 補 participants 全量覆寫 field 表(role 4 值 / owner 保護) | 同上 participants 欄 |
第③類不動(現有深度剛好):3 樹導覽搜尋、7/8/9/10 Excel 匯出入(wizard 三步流程圖夠)、11 進度卡、12 階段推進、5/6 快速配置/啟動。
本 session 未 commit 量極大(35 md source + 39 新 dot + render_html.py),強烈建議分主題 commit 避免混在一起難 review:
commit 鐵則:顯式 git add <檔名>、禁 -am/add -A;避開別線 WIP(docs/specs/v1.8.0/evidence/assets/img/ 截圖 session、FR-046 tracker、docs/交付文件/*.docx、docs/features/ddd-layer-audit/)。html/ 依規則暫不 commit(等 source 收斂再連 source 一起)。push 永遠等 user 明示。
db_schema.json(不信 agent 憑元件名猜、不信 tbls .md);endpoint 對 routes.json;error code 開 common/code/grc_error_code.py 逐一 grep 確認真有(本 session 11 個碼全驗過)。python3 scripts/deliverables/render_html.py "docs/specs/v1.8.0"(全 ✅);.dot 先 dot -Tsvg <檔> -o /dev/null 驗編譯;自查 grep -rEn '192\.168\.|password\s*=|Billows@' <檔> = 0、grep 'GRC 系統' = 0。writing-feature-specs skill 的 references/page-spec-template.md;配色海軍藍 #13294B / 判斷菱形 #FFF6E5 / 例外 #FDEBD3 / 錯誤 #F8DCDC / 成功 #D9E9DC。docs/features/FR-047-2607-feature-spec-handbook/tracker.mddocs/specs/v1.8.0/project-management/project-ssp-inventory.mddocs/specs/v1.8.0/project-management/project-ssp-edit.mddocs/specs/v1.8.0/project-management/project-planning.mdwriting-feature-specs skill(13 節)、closing-and-handoff skill(本文件)scripts/deliverables/out/{db_schema,routes}.jsonscripts/deliverables/render_html.py(約 line 268 專案管理群 / 297 證據管理群)