Session 4 交接 Prompt — C3 PR1 + C4 + C5 完工,接續 C6 / C3 PR2 觀察 / follow-ups

2026-05-23 Session 3 完成後建立。貼以下 ``` 框內容開啟 Session 4。


你正在接手 SSP 在專案內直接編輯 — Phase C Session 4。

## Session 3 完成狀況(已 ship)

### BE — C3 PR1 + C4 合併同 PR ship(受評範圍遷移到 SSP)

| Commit | 主題 |
|--------|------|
| `d2c3df2` | C3 PR1 + C4 主體 — service derive + 410 endpoint + DI cleanup + schema 拿欄位 + Step A/C 拿掉 + DTO + 2 個 error code |
| `ae6d7f1` | C3 PR1 backfill SQL |
| `02a2311` | C3 + C4 unit tests (15 cases 全綠) |
| `1253a92` | C3 PR1 + C4 changelog × 2 + analysis + tracker README |
| `74f4888` | tracker 補 commit hash |
| `f6d4f9d` | fix backfill SQL DISTINCT ON multi-characteristic |

**DB 已執行**:backfill 跑完 8 hardware items + 159 system items(A0 預先補
164 hardware device_id,C3 只補新增的 8 個)。沒任何 AP 的 118 個 project
按 C3-D3 決策 skip(多為 E2E 殘留)。

### FE — C5 SSP tab 完整 ship

| Commit | 主題 |
|--------|------|
| `57caca2` | C5 plumbing + 5 sections + SspTabPanel(16 files / 2185 insertions)|
| `dd28658` | C5 整合 SspTabPanel 進 TabView(方案 A — ProjectPlanningView 原內容包進「控制項實作」tab,新加「SSP」tab) |

**FE 新檔清單**:
- `src/composables/`:useSspContext.js / useSspParties.js / useSspResources.js / useSspSystemCharacteristic.js / useSspLeveraged.js
- `src/components/grc/ssp/`:SspTabPanel.vue / SspBasicSection.vue / SspScopeDevicesSection.vue / SspScopeInfoSystemsSection.vue / SspPartiesSection.vue / SspLeveragedSection.vue
- `src/service/SspService.js` 擴充 19 個 method
- `src/config/api/api.js` 加 13 個 endpoint constants
- i18n: tab_controls / tab_ssp / ssp_* / section.* keys (zh-tw + en)
- changelog: `docs/changelog/2026-05-23-feat-ssp-tab-panel-and-sections.md`

### Phase C 整體狀態(看 BE `docs/features/FR-011.3-2605-ssp-edit-in-project/README.md` tracker)

| Phase | 主題 | 狀態 |
|-------|------|------|
| C1 | OSCAL SSP 角色 master | ✅ shipped (`381d3ec`) |
| C2 | SSP-scoped endpoints (19) | ✅ shipped (C2.1 + C2.2) |
| **C3 PR1** | **受評範圍 derived from SSP + 410** | **✅ shipped (本期,合 C4)** |
| **C4** | **專案 CRUD 拿掉 audit_systems/devices** | **✅ shipped (本期,合 C3 PR1)** |
| **C5** | **FE SSP tab** | **✅ shipped (本期,方案 A TabView)** |
| C3 PR2 | DROP TABLE + 拆 stack | **觀察期中**(1-2 週後做)|
| C6 | 移除專案設定 UI 受評範圍 | spec-ready,FE polish |
| C7 | 06_外部利用服務 sheet | ✅ shipped |
| C8 | role label 清理 | ✅ shipped |

## Session 4 第一件事:驗收 + Push

user 早上要做的(**還沒做**):

1. **BE restart**(無 hot reload):

在 BE repo 跑 (主目錄已是 .)

找既有 process 殺掉再起;或:

python main_socketio.py


2. **BE smoke**:
- `GET /grc/project/<uid>` — 看 devices / audit_systems 來自 current SSP items (not from mapping 表)
- `POST /project-device` — 應該回 410 + `error_code=GRC_410001`

3. **FE smoke**:

cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe npm run dev # port 5180

- 進專案規劃頁 → 看到 2 個 tab:「控制項實作」(default) + 「SSP」
- 切 SSP tab → AP selector + 5 個 accordion(基本資料預展開)
- 編 / 刪 5 個 section CRUD
- 切 AP 看 readonly hint
- `?tab=ssp&section=parties` deep link 直接展開

4. **Push origin(兩 repo)**:

BE: 領先 origin 7 commits (a20959b ~ f6d4f9d)

git push

FE: 領先 origin 2 commits (57caca2 + dd28658)

cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe git push


## Session 4 候選方向

驗收完成後,user 決定下一個 phase。候選:

### 方向 A:C6 移除專案設定 UI 受評範圍(FE polish)

- 範圍:FE only,拿掉專案表單的 audit_systems / devices field
- C4 BE schema 已拿掉,FE 還有 form input — 不對齊
- 預估:半天
- 文件:`docs/features/FR-011.3-2605-ssp-edit-in-project/design-C6.md` + `implementation-plan-C6.md`

### 方向 B:C5 完成度補強

兩個延後項目:

1. **C1 system_menus 整合**
- 目前 `SspPartiesSection.vue` 用 hardcode 9 個 OSCAL role
- 應改吃 `GET /system/menu/ssp_party_role` (C1 已 ship)
- 對應 i18n key `lang.oscal_role.ssp_party_role.<key>.label`

2. **design-C5 §3.1 沒做的 tab**
- design 提到的「AP 列表 / 參與人員」其他 tab
- 本期方案 A 只新加 SSP tab,避免動 ProjectPlanningView 太多
- 評估是否要做(或者放棄這部分 design)

### 方向 C:清理 C2 延後 follow-up

兩個從 Session 2 / 3 跨過來的 follow-up:

1. **multi-round SSP `get_one` bug 修補**
- 位置:`app/oscal/service/ssp_excel_import_app_service.py:_resolve_existing_ssp_shell()`
- 問題:`get_one(SystemSecurityPlanQueryEntity(profile_id=...))` 在 SSP versioning 多輪場景撞 multiple match
- 影響:MF-scoped excel update flow 在多輪 SSP 場景失準
- SSP-scoped 路徑(C2.2 T8)已避開此 bug

2. **`PUT /ssp/<uid>/excel-import/<parse_uid>/decisions` partial-save endpoint**
- design-C2.md §4.5 提的第 5 個 excel-import endpoint
- 目前走「decisions 隨 confirm body 一次性傳入」已能滿足 day-1
- 需要:app service 新 `save_decisions` method + parse_job 狀態擴充

### 方向 D:C3 PR2 — DROP TABLE + 拆 stack(觀察期未到,不可做)

**前提**:PR1 ship 後 1-2 週觀察期,監控 mapping 表無新 INSERT。本期才 ship,
**至少要等到 2026-06-06 後**才可以開始 PR2。

監控 SQL(PR1 後每天跑一次):
```sql
SELECT 'pdm' AS tbl, COUNT(*) FROM compliance.project_device_mapping
WHERE created_at > '2026-05-23'
UNION ALL
SELECT 'pis', COUNT(*) FROM compliance.project_information_systems
WHERE created_at > '2026-05-23';
-- 預期:0 / 0

若非 0 表示有遺漏 caller,要先補修才能進 PR2。

方向 E:BDD e2e scenarios

切到 ~/Projects/Billows/Audit-Manager/compliance-manager-test/ repo 加:

  • 專案啟動 → SSP tab 編輯 5 個 section 的 BDD scenario
  • 410 endpoint regression
  • C5 deep link 行為驗證
§1

環境 / 規範速查

Branch

BE + FE 都同名feature/ssp-import-export-phase3(CLAUDE.md「禁止自行切換 branch」— user 自己切,Claude 不動)

Working tree 狀態

  • BE 領先 origin 7 commits(含 user 1 個 docs commit a20959b
  • FE 領先 origin 2 commits
  • BE 剩 pyproject.toml(dev-only path dep)+ 2 個 zip(user 早前確認不動)
  • FE working tree 乾淨

DB 連線

PGPASSWORD='jedi@123!' psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev

Dev 帳號

  • manual:blsadmin / Billows@123!
  • pytest:blsit / Billows@123!

BE log

log/app.log(BE 專案根目錄)— 任何 BE 行為異常都先 tail / grep 這個

必讀文件

  1. BE CLAUDE.md(會自動載入;含「禁止自行切換 branch」「階段性 commit 不用問」等規範)
  2. docs/features/FR-011.3-2605-ssp-edit-in-project/README.md(tracker — 必看 C3 PR2 / C6 行)
  3. docs/changelog/2026-05-23-tweak-c3-scope-migrate-to-ssp-pr1.md(C3 PR1 改動細節)
  4. docs/analysis/2026-05-23-c3-scope-migration-decisions.md(為何偏離 design 的 7 個決策)
  5. 走 C6 → FE CLAUDE.md + docs/features/FR-011.3-2605-ssp-edit-in-project/design-C6.md + implementation-plan-C6.md
§2

C3 PR1 + C4 + C5 留下可重用的基礎設施

接下來的 phase(C6 / C3 PR2 / 其他)可直接用:

BE

  • domain/oscal/service/ssp_project_resolver.py
    • resolve(ssp_uid)SspProjectContext(ssp, ap, project) (raise NotFound)
    • resolve_current_ssp(project_id)SspProjectContext | None (本期新加)
  • common/code/grc_error_code.py 新加:
    • GRC_PROJECT_DEVICE_DEPRECATED = GRC_410001
    • GRC_PROJECT_INFO_SYSTEM_DEPRECATED = GRC_410002

FE

  • src/composables/useSspContext.js — projectUid → reactive SSP context
  • src/composables/useSsp{Parties,Resources,SystemCharacteristic,Leveraged}.js — module-scope cache
  • src/components/grc/ssp/ — 6 個 .vue 元件
  • src/service/SspService.js 擴充 19 個 method (對齊 C2 的 19 個 endpoint)
§3

開工建議流程

  1. 先問 user 走哪個方向(A / B / C / E;D 觀察期未到不可選)
  2. 跑 pre-flight(Session 4 開始時):
    git log --oneline | head -10
    git status --short
    # 確認 BE 7 + FE 2 commits 已 push origin(user 早上會做)
  3. 依方向開新任務清單(TaskCreate)
§4

重要規範回顧(Session 3 期間落實)

CLAUDE.md memory feedback_stage_commit_no_ask.md

階段性 commit 不用問 — 子 task / milestone / changelog / issue 完成後 commit 直接做, 不停下問 user;只有重大決策(架構衝突、需選 A/B/C 方案、breaking change)才停

Session 3 期間實踐:14 個 BE task → 5 commits;12 個 FE task → 2 commits, 中間只在 4 個重大決策點停下問(方向選擇 / 118 個 no-AP project / Step A 拿掉範圍 / TabView 整合方案)。

§5

Session 3 期間關鍵決策(已寫進 docs/analysis/2026-05-23-c3-scope-migration-decisions.md

  1. resolve_current_ssplatest AP 不限 status,對齊既有 ProjectCurrentSspService._latest_ap
  2. 擴充 SspProjectResolver 而非新建 ssp_current_resolver.py(重用 DI 注入)
  3. Step A 整段拿掉(含 SystemCharacteristic auto-snapshot + PSCM)— design 沒提 PSCM 但邏輯上一起
  4. JobExecutionDevice 系列不動(屬另一範疇)
  5. C3 PR1 + C4 合併同 PR(plan 寫「搭配 C4」明示)
  6. 118 個 no-AP project skip(按 C3-D3 決策)
  7. schema class 保留(OscalProjectStartRequest 內欄位拿掉但 AuditSystemInputSchema 等 class 留)
§6

Session 3 期間意外事件

backfill SQL 第一次跑 bug

  • INSERT 8 hardware + 210 system items(>pis 165)
  • 原因:SSP 251 有 4 個 characteristic,LEFT JOIN 撞 row 展開
  • Rollback 218 row + 修 SQL 加 DISTINCT ON 重跑
  • 第二次:8 hardware + 159 system items(正確)
  • 已 commit f6d4f9d fix 進 SQL 檔,未來重跑就是修正版

教訓:SQL backfill 有 LEFT JOIN 時必須先確認多對一 / 一對多關係,加 DISTINCT。


---

## 補充:Session 3 期間調整的小事項

寫進 handoff 但 Session 4 可選擇性回顧:

1. <strong>`isProjectManager` 模式重用</strong>:FE TabView 整合時加 `myParticipantRole` computed,仿既有 `isProjectManager` pattern 從 `projectParticipants` + `userInfo.value.uid` 對應
2. <strong>C5 偏離 design 部分</strong>:design-C5 §3.1 提到「AP 列表 / 概覽 / 參與人員 / SSP」4 個 tab,本期方案 A 只在 ProjectPlanningView 加「控制項實作 + SSP」2 個 tab,避免 monolithic refactor 太大
3. <strong>SSP `system_characteristic` 為 1:N</strong>(同一個 SSP 可能有多個 characteristic,dev DB 中 SSP 251 有 4 個)— FE `useSspSystemCharacteristic` 假設 BE GET 回單筆(依 BE service.get(ssp_uid) 行為);若未來 BE 改回 array 要重新評估
4. <strong>CLAUDE.md memory 新增</strong>:對話紀錄主動從 JSONL extract 規範(不憑記憶重建,用 `scripts/extract_claude_sessions.py`)— user 在 session 中間更新
5. <strong>ProjectPlanningView 2125 → ~2145 行</strong>:方案 A TabView 整合只加 ~20 行,原既有功能完全不動(左側 tree / 右側 control/AO 編輯 / 6 個 dialog / batch menu / FlowPhaseBanner / breadcrumb 等)