# TRP-002　NFR 驗證計畫（60 小節 ／ 874 項）

| 項目 | 內容 |
|---|---|
| 文件編號 | TRP-002 |
| 版本 | **1.2** |
| 狀態 | 🟡 **N2 批次執行中（前兩項完成；證據矩陣 ✅20／📄19）** |
| 撰寫日 | 2026-10-02 |
| 撰寫者 | WorkBuddy AI（開發團隊） |
| 緣起 | BEAM PMO：「**請出一份 NFR 驗證計畫（把 60 小節分成「可本地驗證／需外部環境／需客戶參與」三類，標出可立即做的）**」 |
| 上游 | `BRD-003`（60 小節清單，單一真實來源）／`TRP-001 §6.2`（8 項準出）／`GOV-005 §1`（NFR 三軸） |
| 關聯 | `TRR-001`（測試結果報告）、`SAD-006`（部署與可觀測性）、`SAD-005`（安全） |
| **本計畫要回答的問題** | 這 **60 小節**，**哪些今天就能在本機驗**、**哪些非等外部環境不可**、**哪些要客戶配合**——以及**現在立刻能動手的是哪幾件** |

---

## 1. 現況：為什麼需要這份計畫

`HANDOVER §1` 之 NFR 現況為 **「設計 100%／驗證 3.3%（2/60）」**。
`TRR-001 v2.0` 首度對照 `TRP-001 §6.2` 之 8 項準出——**僅 2 項達成**；**效能／一致性／安全掃描從未執行**。

> ⚠️ **但「未驗證」不等於「都要等外部」**——這正是本計畫要拆開的：
> **60 小節中，39 小節（689 項／78.8%）的驗證素材在本機已經齊備**。
> 過去把它們一律記為「未驗證」，等於**自我設限**（同 `GOV-007` 之「外部系統沒給 ≠ 被阻塞」）。

---

## 2. 分類法（判定準則）

| 類別 | 判定準則 | 交付方式 |
|---|---|---|
| **Ａ　可本地驗證** | 驗證所需之**程式、資料、服務、工具**在本機（`ops/local/docker-compose.yml` ＋ Oracle 26ai Free ＋ PostgreSQL ＋ Redis ＋ Kafka KRaft ＋ Keycloak ＋ OTel／Jaeger／Prometheus／Loki／Grafana ＋ Garage）**皆已具備**；或屬**靜態檢核**（掃描器／契約／型別／文件） | 可直接產出**可稽核證據**（報告／截圖／掃描輸出） |
| **Ｂ　需外部環境** | 需要**正式機房、正式 DB（RAC／HA）、HSM／KMS、壓測環境、企業 IdP、正式憑證、監控平台**等——**本機無法等效** | **本地先做可替代之部分**（見各列「本地替代」），其餘待環境 |
| **Ｃ　需客戶參與** | 屬**決策、文件、認證、分工、SLA**——**技術上無法由我方單方完成** | 提供**檢核表**，由客戶／PM 逐項確認 |

> ★ **一個小節可能橫跨兩類**——本表取**主類別**，並於「備註」載明**次類別之範圍**。
> ★ **Ａ 類 ≠ 已驗證**——Ａ 類只代表「**可在本地驗證**」。**已實際驗證者仍為 2/60**（見 §7.4）。

---

## 3. 總覽

| 類別 | 小節數 | 占比 | NFR 項數 | 占比 | 說明 |
|---|---:|---:|---:|---:|---|
| **Ａ　可本地驗證** | **39** | 65.0% | **689** | 78.8% | ★ **本計畫之重點**——素材已備，缺的是「跑一次並留證」 |
| **Ｂ　需外部環境** | **13** | 21.7% | **137** | 15.7% | 其中 **多數可先做本地替代** |
| **Ｃ　需客戶參與** | **8** | 13.3% | **48** | 5.5% | 決策／文件／分工 |
| **合計** | **60** | 100% | **874** | 100% | 與 `BRD-003 §2` 一致 ✅ |

---

## 4. Ａ 類　可本地驗證（39 小節 ／ 689 項）

> **欄位說明**：「現有工具資產」＝本機**已經存在**、可直接拿來驗的東西；
> 「立即」＝**不需要任何新工具**即可開跑。

### 4.1　B.1 基礎設施（2 小節 ／ 25 項）

| 小節 | 項數 | 驗證方法 | 現有工具資產 | 立即 | 備註 |
|---|---:|---|---|:--:|---|
| 監控機制 | 21 | 指標與告警規則驗證、儀表板檢視 | ★ OTel＋Jaeger＋Prometheus＋Loki＋Grafana **已接線 19/19 模組**（`#A-27`）；`prometheus.yml` 5 job | ✅ | 告警規則需逐一建檔比對 |
| 變更作業 | 4 | 變更單流程稽核、CI 紀錄 | `GOV-003 §7`；git 紀錄 | ✅ | 需補「變更單模板」 |

### 4.2　B.2 系統規格（35 小節 ／ 623 項）

| 小節 | 項數 | 驗證方法 | 現有工具資產 | 立即 | 備註 |
|---|---:|---|---|:--:|---|
| System Architecture | 14 | 架構檢核表、依賴規則掃描 | `LayeringTest`（各服務）、`validate_sql` SQL-07 | ✅ | — |
| System Monitoring | 11 | 監控覆蓋率檢核 | 同「監控機制」 | ✅ | — |
| Front-end System | 15 | 瀏覽器相容性矩陣、前端測試 | `tsc --noEmit`；★ **前端無測試框架** | ⚠️ | **需先補 vitest**（見 §7.2）；多瀏覽器矩陣需額外安裝 |
| Mobile and Tablet Device | 1 | 響應式斷點測試 | headless Chrome（CDP）＋ 截圖 | ✅ | — |
| SSO | 1 | `SCS-022 §8` 五情境端到端 | Keycloak 本機 ＋ `tools/verify_sso_pkce.py` | ✅ | — |
| 第三方套件 | 1 | 套件清冊與授權／漏洞掃描 | `package.json`／`gradle/libs.versions.toml` | ⚠️ | **需裝掃描器**（見 §7.2） |
| 前端語言(front-end) | 1 | 靜態檢查與型別檢查 | `npm run typecheck` | ✅ | — |
| 支援多國語系 | 1 | 語系切換測試、資源檔覆蓋率 | 前端 i18n 資源檔 | ✅ | — |
| UI/UX | 4 | 設計規範符合性檢核 | `SDD-007 §2` 設計規範 ＋ 截圖 | ⚠️ | 需 **UX 人員**共同判定（次類別 **Ｃ**） |
| Authentication | 21 | 登入、MFA、鎖定策略；JWT 驗證 | Keycloak 本機；`JwtRoleConverter`（`SCS-022 §7`） | ✅ | **MFA** 需企業 IdP（次類別 **Ｂ**） |
| Authorization | 11 | RBAC 矩陣逐角色驗證 | `JwtRoleConverter`；Keycloak realm roles | ⚠️ | ★ **平台無 RBAC 資料源**（`CR-035 §2.3`）→ 角色矩陣之**權威來源需客戶確認**（次類別 **Ｃ**） |
| Connection issue | 3 | 逾時、重試、斷線復原 | 可停容器做故障注入 | ✅ | — |
| Transaction security | 14 | 加密與簽章驗證、金鑰輪替 | `KeyProvider`（機制已實測，`#A-24`～`#A-26`） | ✅ | **金鑰輪替**需 HSM／KMS（次類別 **Ｂ**） |
| 資料儲存的安全性 | 1 | 靜態加密與遮罩驗證 | `KeyProvider` ＋ Oracle 實機密文往返（已實測） | ✅ | ★ **本項即「已驗證 2/60」之一** |
| JavaScript程式壓縮 | 1 | 建置產物檢視 | `vite build` 產物 ＋ sourcemap 策略 | ✅ | — |
| Audit Trail | 11 | 軌跡完整性與不可竄改 | `SDD-001 §8`、`CSP-004 §4`；Oracle 稽核欄位 | ✅ | — |
| Data Storage | 8 | 資料模型與儲存策略檢核 | `SDD-001 §3`、`validate_sql` 70 檔 0 違規 | ✅ | — |
| 資料傳輸 | 5 | TLS 組態與傳輸加密驗證 | 本機可驗組態（自簽憑證） | ✅ | **正式憑證鏈**需外部（次類別 **Ｂ**） |
| Database Infrastructure | 27 | DB 組態與 HA 驗證 | 本機 Oracle 26ai Free 組態、`V1`～`V9` 遷移 | ⚠️ | **HA／RAC** 需正式環境（次類別 **Ｂ**） |
| Data Structure | 23 | 資料字典與正規化檢核 | `SDD-001 §3.4`（`all_tab_columns` 可實查） | ✅ | — |
| Overview | 25 | 架構總覽符合性檢核 | `SAD-001`；`gen_openapi` **96 端點 0 錯誤** | ✅ | — |
| Core System Layer | 82 | 領域模型與流程設計檢核 | ★ **全量 1096 單測 0 失敗**（194 類別） | ✅ | — |
| Integration Layer | 93 | 介接契約與整合測試 | 契約 17 份；Kafka KRaft 可**注入事件**（`#A-156 ⑥`）；Outbox | ✅ | — |
| API Support | 9 | OpenAPI 契約驗證與契約測試 | `gen_openapi` ＋ `verify_contract_dto` | ✅ | — |
| API設計與管理 | 5 | API 治理檢核（版本、速率、金鑰） | gateway **Redis 限流**（`#A-73`）；`SAD-004 §3` | ✅ | — |
| Presentation Layer | 16 | 頁面清單與元件規範檢核 | 側欄 **30 頁**；`SDD-007 §5.4` 逐鈕定義 | ✅ | — |
| Application Monitoring | 66 | APM 覆蓋率與告警驗證 | ★ 同「監控機制」（19/19 已接線） | ✅ | — |
| Application Developement & tools | 23 | 工具鏈清冊與建置流程驗證 | Gradle 9.7.1／Node 22／`tools/*.py` 17 支 | ✅ | — |
| Application Version control | 33 | 分支策略與版控稽核 | git 紀錄（本日 6 提交可稽核） | ✅ | — |
| Application Change Control | 23 | 變更流程稽核 | `GOV-003 §7`、`docs/05-change-requests/`（`CR-036` 等） | ✅ | — |
| application administratoration | 14 | 管理介面權限驗證 | Keycloak 角色矩陣 | ⚠️ | **企業 AD／IdP** 整合需外部（次類別 **Ｂ**） |
| Application Documentation | 20 | 交付物清冊完整性檢核 | `GOV-001`；`docs/` 146 檔 | ✅ | — |
| SOA | 23 | 服務邊界與契約檢核 | **17 服務 × 17 獨立 schema**；`validate_sql` SQL-07 **0 違規** | ✅ | — |
| Operation | 9 | 營運手冊與批次作業驗證 | `OPS-001`；批次可本機跑（`UNMATCHED` 產生器等） | ✅ | — |
| Monitoring | 8 | 監控項目逐項驗證 | 同「監控機制」 | ✅ | — |

### 4.3　B.3 微服務／分散式／雲原生（2 小節 ／ 41 項）

| 小節 | 項數 | 驗證方法 | 現有工具資產 | 立即 | 備註 |
|---|---:|---|---|:--:|---|
| 微服務架構原則 | 25 | 服務獨立性、**資料私有性**、契約測試 | ★ **SQL-07 跨 schema 直連 = 0**（`validate_sql` 70 檔）；17 服務獨立部署 | ✅ | ★ 本項有**最強證據**：架構層已由掃描器守住 |
| 原雲生原則 | 16 | 容器化、健康檢查、組態外部化 | `ops/local/docker-compose.yml`；`/actuator/health` 17/17 | ✅ | — |

---

## 5. Ｂ 類　需外部環境（13 小節 ／ 137 項）

> **每列皆載明「本地替代」**——**先做能做的**，不因等環境而整項停擺（`GOV-007` 鐵則）。

| 小節 | 項數 | 需要什麼 | **本地替代（可先做）** | 主責 |
|---|---:|---|---|---|
| 效能測試 | 12 | 壓測環境（近正式規格） | ★ **可先寫壓測腳本**（k6／JMeter）＋**單機基線**（標明非 SoW 門檻）；`TRR-001` 已記 L-5 單機限制 | QA |
| 容量規劃 | 3 | 容量模型 ＋ 壓測曲線 | 容量**模型試算**（依單機基線外推，標明假設） | SRE／SA |
| Capacity Planning | 10 | 同上 | 同上 | SRE／SA |
| 安全測試 | 2 | 授權 ＋ 測試環境（弱掃／滲透） | ★ **SAST 可本地做**（SonarQube／Semgrep 本地容器）＋ **依賴漏洞掃描**（`npm audit`／`dependency-check`） | SEC |
| 備援機制 | 5 | DR 環境（RTO／RPO 量測） | ★ **故障注入可本地做**（停容器：Kafka／Redis／Oracle／服務）——驗「降級行為」而非 RTO／RPO | SRE |
| System Recovery | 8 | 同上 | 同上 ＋ **備份／還原程序演練**（Oracle RMAN 本地 PDB） | SRE |
| 維運管理 | 30 | 正式環境 Runbook 演練 | ★ **Runbook 撰寫可先做**（`OPS-001`）；以本地環境**走一遍**並記錄差異 | SRE |
| 帳號管理 | 5 | 企業 IdP／AD | Keycloak **角色與群組矩陣**（本機）＋ 權限最小化檢核 | SEC |
| 機房作業 | 6 | 機房與網路 | **組態檢核表**（以 `docker-compose` 之網路拓撲為樣本） | SRE |
| 開放系統平台 | 4 | 正式平台（OS／中介軟體） | **版本相容性矩陣**（現行版本 vs SoW 要求） | SA |
| System Platform | 8 | 正式平台能力 | **平台能力對照表**（逐項標「本機已驗／待正式環境」） | SA |
| Database Admin. | 29 | DBA 環境（備份還原、權限、稽核） | ★ **備份還原程序**可本地演練（PDB export／import）；**權限矩陣**可本地建 | DA／SRE |
| Equipments | 15 | 設備規格與配置 | **規格檢核表**（對照 SoA／SoW 之硬體需求） | SRE |

---

## 6. Ｃ 類　需客戶參與（8 小節 ／ 48 項）

| 小節 | 項數 | 需要客戶什麼 | 我方提供 |
|---|---:|---|---|
| 公司能力 | 7 | 實績與認證文件查驗 | 文件清冊（DXC／ACI 實績） |
| 專案管理能力 | 4 | 治理文件與流程查驗 | `GOV-002`／`GOV-003` 之治理文件 |
| Vender development | 9 | 分工確認 | 分工矩陣（依 `GOV-002`） |
| Taiwan's agent or branch's development | 6 | 分工確認 | 同上 |
| SI vender's development | 6 | 分工確認 | 同上 |
| Guarantee & Maintenance | 3 | 保固範圍與 SLA 確認 | `OPS-001` 之保固條款草案 |
| Package | 7 | **套裝與自建邊界確認** | 現行邊界（哪些用套裝／哪些自建） |
| Others 其他 | 6 | 逐項人工確認 | 逐項清單（需先從建議書附錄 B 抽出） |

---

## 7. ★★ 可立即做（本計畫之核心）

### 7.1　不需任何新工具——今天就能跑並留證（依價值排序）

| 序 | 動作 | 對應 NFR 小節 | 產出 | 預估 |
|---:|---|---|---|---|
| **1** | **跑一次「NFR 證據盤點」**：把已存在的 17 支 `tools/*.py` ＋ 1096 單測 ＋ 監控截圖，**逐項對應到 60 小節**，標明「已有證據／缺證據」 | 全部 | **NFR 證據對照表**（本計畫 §4 之落地版） | 小 |
| **2** | **監控三支柱截圖留證**（Grafana 儀表板／Prometheus targets／Jaeger trace／Loki log） | 監控機制／System Monitoring／Application Monitoring／Monitoring | 截圖 ＋ 指標清單 | 小 |
| **3** | **故障注入演練**（停 Kafka／Redis／Oracle／各服務，記錄降級行為） | 備援機制／Connection issue／Transaction security | 演練報告 | 中 |
| **4** | **SSO 五情境端到端**（`SCS-022 §8`；已有 `verify_sso_pkce.py`） | SSO／Authentication | 執行紀錄 | 小 |
| **5** | **架構／邊界檢核報告**（`LayeringTest` ＋ SQL-07 ＋ 17 schema 獨立性） | System Architecture／SOA／微服務架構原則 | 報告 | 小 |
| **6** | **契約一致性全掃**（`verify_contract_dto` 逐服務 ＋ 96 端點） | API Support／API設計與管理／Integration Layer | 掃描輸出 | 小 |
| **7** | **備份／還原程序演練**（Oracle PDB export／import） | Database Admin.／System Recovery | 演練報告 | 中 |
| **8** | **Runbook 撰寫 ＋ 本地走查** | 維運管理／Operation | `OPS-001` 增補 | 中 |

### 7.2　★ 需先補「工具缺口」——補完即可驗（**目前完全沒量過**）

| 序 | 缺口 | 影響之 NFR／準出 | 補法 | 預估 |
|---:|---|---|---|---|
| **1** | ★★ **覆蓋率從未量測**（`backend` **完全未配置 JaCoCo**） | `TRP-001 §6.2` 第 1 條「**行覆蓋 ≥80%／分支 ≥70%／Mutation ≥75%**」——**目前無法判定** | 於 `backend/build.gradle` 加 JaCoCo plugin → 跑全量 → 產報告 | 小 |
| **2** | ★ **前端零測試框架**（`devDependencies` 僅 `typescript`＋`vite`） | Front-end System(15)／Presentation Layer(16)／UI/UX(4)／JavaScript壓縮(1) | 加 `vitest` ＋ 少量元件測試；E2E 用既有 headless Chrome（CDP） | 中 |
| **3** | **依賴漏洞掃描未執行** | 第三方套件(1)／安全測試(2) | `npm audit`（前端）＋ OWASP dependency-check（後端 Gradle plugin） | 小 |
| **4** | **SAST 未執行** | 安全測試(2) | Semgrep／SonarQube（本地容器，**不碰客戶環境**） | 中 |
| **5** | **NFR 對應未自動化** | 全部 60 小節 | ★ 新增 `tools/verify_nfr.py`：讀 `BRD-003` 之 60 小節 ＋ 各工具輸出 → **產出可稽核之證據矩陣** | 中 |
| **6** | **壓測腳本未撰寫** | 效能測試(12)／容量規劃(3)／Capacity Planning(10) | k6／JMeter 腳本（**先可單機跑基線**） | 中 |

### 7.3　Ｂ 類之「先做替代」（不等環境）

見 §5 各列之「本地替代」。**建議一併納入第一批**：SAST／依賴掃描（不需客戶環境）、故障注入（本地容器即可）。

### 7.4　★ Ａ 類 ≠ 已驗證——必須說清楚

**Ａ 類 39 小節（689 項）只代表「可在本地驗證」**。以 `HANDOVER §1` 之計法，
**實際已驗證者仍為 2/60**。本計畫之價值即為**把這 37 小節的差距具體化為「可執行清單」**。

> ⚠️ **併發現一項帳務缺口**：`HANDOVER §1` 之「**已實測 2 項**」**未在 `BRD-003` 標明是哪 2 小節** →
> 應補註（推測為「資料儲存的安全性」與「錯誤處理」相關小節，惟**未經明載**，**不臆測**）。
> **列為本計畫之收尾項**。

---

## 8. 與 `TRP-001 §6.2` 之 8 項準出對照

| # | 準出條件 | 現況 | 分類 | 可立即？ |
|---:|---|---|:--:|:--:|
| 1 | 單元測試行覆蓋 ≥80%、分支 ≥70%、Mutation ≥75% | ★ **從未量測**（JaCoCo 未配置） | **Ａ** | ✅ **§7.2 #1** |
| 2 | 禁止模式掃描（scaffold／mockdata／faketest）0 命中 | ✅ **已達成**（全庫 0 命中，含 frontend） | **Ａ** | — |
| 3 | 68 項 FR 功能劇本全部 Pass | 🟡 FR 99.1%；**劇本逐項 Pass 之紀錄未完整** | Ａ／Ｃ | 需補劇本對照 |
| 4 | 17 項 POC 驗收全部 Pass | 🟡 **85.3%**（13 ✅／3 🟡／1 ⚪） | Ａ／Ｂ | #17 需壓測（**Ｂ**） |
| 5 | 效能：P95 ≤ 500ms、≥1,000 TPS、>2,000 TPS | ⚪ **未執行** | **Ｂ** | 先寫腳本（§7.2 #6） |
| 6 | 引擎一致率 ≥99.99%、A 類差異 0 | ⚪ **未執行** | **Ｂ** | 需對帳環境 |
| 7 | 安全掃描無高／嚴重漏洞；個資遮蔽經滲透驗證 | ⚪ **未執行** | **Ｂ** | ★ **SAST／依賴掃描可先做**（§7.2 #3／#4） |
| 8 | `TRR-001` 記載完整劇本、資料、缺陷狀態 | ✅ **已完成**（`#A-108`） | Ａ | — |

**小結**：8 項中 **2 項已達成**（#2／#8）；**4 項可本地先做或部分先做**（#1／#3／#4 部分／#7 部分）；**2 項非等外部不可**（#5／#6）。

---

## 9. 執行順序建議

| 批次 | 內容 | 對應 | 依賴 |
|---|---|---|---|
| **N1** | ★ **工具缺口補齊**：JaCoCo（覆蓋率）＋ 依賴漏洞掃描 ＋ `verify_nfr.py` | §7.2 #1／#3／#5 | 無 |
| **N2** | ★ **本地可驗之證據產出**：監控截圖／SSO 五情境／架構邊界報告／契約全掃 | §7.1 #2／#4／#5／#6 | N1 |
| **N3** | **故障注入 ＋ 備份還原 ＋ Runbook 走查** | §7.1 #3／#7／#8 | N2 |
| **N4** | **SAST ＋ 前端測試框架 ＋ 壓測腳本（單機基線）** | §7.2 #2／#4／#6 | N1 |
| **N5** | **Ｂ 類「先做替代」之其餘**（§5 各列） | §5 | N3 |
| **G4／G5** | 需外部環境之正式驗證（效能／DR／滲透） | §5／§8 #5／#6 | **客戶環境** |

---

## 10. 誠實揭露（本計畫之限制）

1. **Ａ／Ｂ／Ｃ 為「驗證所需條件」之分類，非「完成度」**——Ａ 類 39 小節中**多數尚未實際驗證**。
2. **項數（874）取自 `BRD-003`**，其上游為建議書附錄 B；**逐項內容未於本計畫重述**（單一真實來源原則）。
3. **「已驗證 2/60」之那 2 小節未在 `BRD-003` 明載** → 不臆測，列為收尾項（§7.4）。
4. **本計畫未涵蓋** `BRD-003 §4` 之「關鍵非功能指標」逐項**驗證方法設計**（僅列於 §8 之準出對照）——如需可另立 `TRP-003`。
5. **Ｂ 類之「本地替代」不等於正式驗證**——例如故障注入可驗「降級行為」，但**不能**替代 RTO／RPO 量測。

---

## 11. ★★ N1 批次執行結果（2026-10-02，`#A-160`）

N1（工具缺口補齊）**已完成 N1-1／N1-2／N1-3**：

| 項 | 內容 | 結果 |
|---|---|---|
| **N1-1** | **JaCoCo 覆蓋率**（`backend/build.gradle.kts` ＋ 產生器模板**兩邊都動**） | ★ **行 53.7%／分支 46.8%** → 準出 #1 **❌ 未達** |
| **N1-2** | **依賴漏洞掃描**（前端 `npm audit`；後端 **新增 `tools/scan_deps.py`**／OSV） | ★ **後端 3 CRITICAL＋10 HIGH**；**前端 1 HIGH＋3 MODERATE** → 準出 #7 **❌ 未達** |
| **N1-3** | **`tools/verify_nfr.py`**（NFR 證據矩陣；含 `BRD-003` ↔ 分類之**一致性守門**） | ★ 產出 `docs/08-evidence/NFR證據矩陣.md` |

### 11.1 ★★ 證據矩陣結果（四態）

| 狀態 | 小節數 | 意義 |
|---|---:|---|
| ✅ 有**執行證據**且通過 | **13** | 真的跑過且過 |
| ❌ 有執行證據但**未通過** | **2** | `第三方套件`（18 筆漏洞）／`Core System Layer`（覆蓋率未達） |
| 📄 **設計已備（未驗證）** | **24** | ★ **只有文件、尚無執行證據** |
| ⚠️ 需人工留證／需外部／需客戶 | **21** | 對應 Ｂ 13 ＋ Ｃ 8 |

> ★★ **這張表才是真話**：60 小節中**只有 13 小節有「跑過且過」的證據**，
> **24 小節僅止於「設計已備」**——與 `HANDOVER §1` 之「設計 100%／驗證 3.3%」一致。
> ⚠️ **📄 不得計為通過**（`GOV-007` 反假綠）。

### 11.2 ★ 工具開發中修正之三個缺陷（誠實記錄）

| # | 缺陷 | 後果 | 修正 |
|---|---|---|---|
| 1 | 誤以為 OSV `querybatch` 回完整物件 | **全數 UNKNOWN／無修復版本**（誤導性報告） | 實測發現只回 `{id, modified}` → 增逐筆取詳情 |
| 2 | 修復版本**跨分支混收** | 把 2.x 修復版本誤報為 3.x 者 | 限定 `affected[].package.name == 查詢套件` |
| 3 | 初版以「**有檔案**」當作證據（`docs` token） | 「監控機制」被標 ✅，證據卻只是「有 100 份文件」＝**假綠** | 改為**具名文件**（`doc:SAD-006`）＋ 新增 **📄 設計已備** 態，**與 ✅ 分開** |

### 11.3 對 `TRP-001 §6.2` 之影響

| # | 準出條件 | 執行前 | **執行後** |
|---:|---|---|---|
| 1 | 行覆蓋 ≥80%／分支 ≥70%／Mutation ≥75% | 無法判定 | ❌ **未達**（Mutation 仍未接入） |
| 7 | 安全掃描無高／嚴重漏洞 | 未執行 | ❌ **未達** |

**準出達成數：2 → 2**（#1／#7 由「無法判定／未執行」變為「**已量測且明確未達**」——
**這是進步**：從「不知道」變成「知道差多少」）。

### 11.4 證據文件

- `docs/08-evidence/N1_工具缺口補齊與量測結果.md`（覆蓋率逐模組 ＋ 漏洞清單與修復版本）
- `docs/08-evidence/NFR證據矩陣.md`（`verify_nfr.py` 產生，**請勿手改**）

---

## 13. ★★ N2 批次執行結果（2026-10-06，`#A-223`／`#A-224`）

N2（本地證據產出）之**前兩項已完成**——★★ **證據矩陣：✅15 → 20；📄 24 → 19**。

### 13.1 ★★ N2-a：架構邊界檢核（`#A-223`）

★ **新增工具 `tools/verify_architecture.py`**——★ **零相依、可失敗、含 `--selftest`**。

| # | 檢核項 | 依據 | 實測 |
|---|---|---|---|
| A1 | **容器化**：可部署模組皆有 `Dockerfile` | 雲原生「可部署單元」 | ★ **19／19** |
| A2 | **健康探測**：皆有 `spring-boot-starter-actuator` | 雲原生「可探活」 | ★ **19／19** |
| A3 | **無狀態**：零 `HttpSession` | 12-factor「無狀態行程」 | ★ **0 處** |
| A4 | **分層依賴方向**：`application` 零 import `infrastructure` | `CSP-002 §6.3` | ★ **0 處** |
| A5 | **設定外部化**：無**純字面值**密碼 | 12-factor「組態存於環境」 | ★ **0 處** |
| A6 | **服務間呼叫逾時** | `Connection issue` | ★ connect **2000ms**／request **3000ms**／backoff **200ms**／maxRetries **1** |
| A7 | **埠不重複** | 微服務「獨立部署」 | ★ 推導 **19 埠（8081–8101）**、保留 `[8090]`、**無重複** |
| A8 | **資料庫身分獨立** | 微服務「資料擁有權」 | ★ **17 個身分、無重複** |

**結果：8／8 通過**（`--selftest` **8/8**）。

> ★★★ **真機反駁我方之假設（2 項，本工具初版之缺陷——皆已修正）**：
> ① ★★ **A6 偽陽性**：初版檢查「每個服務之 yml 是否有逾時組態」→ 實測 16 個服務「缺」——
>   ★ **偽陽性**：逾時之**保證在程式碼預設值**（`ServiceClientProperties`），
>   ★ **各服務不設才是正確的**（沿用共用預設）→ ★ 改為檢查**預設值本身**。
> ② ★★★ **A7 假綠**：初版掃 `application*.yml` 之 `server.port` → 實測 **0 個埠**
>   （★ 埠由啟動引數 `--server.port=` 帶入，**不在 yml**）→ ★ **空量測卻報 ✅＝假綠**。
>   → ★ 改以**規格側單一真實來源** `spec/services.yaml` 推導（`port_start` ＋ 服務順序 ＋ 平台顯式埠）。
>
> ★ **教訓**：★★ **「檢核項若量不到東西，必須報『無法判定』而非 ✅」**——
> 本專案之 `GOV-007` 反假綠原則同樣適用於**檢核工具自身**。

★ **證據**：`docs/08-evidence/N2_架構邊界檢核.md`（機器產生）。
★ **轉換之小節**：**原雲生原則**（16 項）、**Connection issue**（3 項）。

### 13.2 ★★ N2-b：SSO 五情境端到端（`#A-224`）

★ **實測方式**：以 `CARDCORE_SECURITY_ENABLED=true` 啟動 `party-service`（8084），
再跑 `tools/verify_sso_pkce.py`（★ **真實 Keycloak ＋ 真實後端**）。

| # | 情境 | 實測 |
|---|---|---|
| ① | PKCE `code_verifier` 43 字元（RFC 7636 要求 43~128）＋ **S256** | ✅ |
| ② | 授權端點 → HTTP **200** | ✅ |
| ③ | 送出帳密 → HTTP **302** | ✅ |
| ④ | 取得 authorization code | ✅ |
| ⑤ | 交換 `access_token`（1245 字元、`expires_in` 900s） | ✅ |
| ⑥ | ★★ **無 token → 401**（`CC-PLT-4010`） | ✅ |
| ⑦ | ★★★ **帶真 token → 200 並回真實資料**（`partyNo: P001`／`name: 王小明`／`idNoMasked: A1******89`） | ✅ |
| ⑧ | ★★ **偽造 token → 401** | ✅ |
| ⑨ | `refresh_token` → 200、新 token | ✅ |

**結果：✅ 通過**（工具 exit 0）。

> ★★ **真機反駁我方之假設（1 項）**：★ 首次以 **RAW(16) 之 hex**（`018F2A3B…`）當
> `partyId` → 帶 token 回應為 **400 `CC-PTY-4001`「無效的識別碼格式（須為 UUID）」**。
> ★ **這不是缺陷**——★ 端點要求 **UUID 字串**，★ **是我方輸入格式之誤**；
> ★ 改以 `018f2a3b-0000-0000-0000-000000000050` 重跑即得 **200 真實資料**。
> ★ **併記**：工具之判讀為「**非 401 即通過**」——★ 若只跑首次，會得到
> 「token 被接受」但**未證明回傳真實資料**之**弱證據**；★ **重跑後方為強證據**。

★ **併為 `verify_sso_pkce.py` 新增 `--out`**——產出**含機器標記與 verdict 之執行紀錄**，
供 `verify_nfr.py` 之 `sso` 檢核讀取（★ **無標記或 verdict=FAIL 一律不通過**）。

★ **證據**：`docs/08-evidence/N2_SSO五情境驗證.md`（機器產生）。
★ **轉換之小節**：**SSO**（1 項）、**Authentication**（21 項）、**Authorization**（11 項）。

### 13.3 ★ 證據矩陣變化

| 狀態 | N1（`#A-160`） | `#A-216` | **N2（本輪）** |
|---|---:|---:|---:|
| ✅ 有執行證據且通過 | 13 | 15 | ★ **20** |
| ❌ 有執行證據但未通過 | 2 | 0 | **0** |
| 📄 **設計已備（未驗證）** | 24 | 24 | ★ **19** |
| ⚠️ 需人工留證／需外部／需客戶 | 21 | 21 | 21 |

> ★★ **如實揭露**：★ 標為 ✅ 之小節**代表「已有執行證據且通過」**，
> ★ **不代表該小節之全部項數皆已逐項驗證**——★ 例如「原雲生原則」（16 項）之
> 自動擴縮／多區部署**仍待外部環境**；★ 惟其**架構面之可查證事實**已由 A1～A8 量測。
> ★ **本計畫之立場**：★ **寧可標明範圍，不以「整節 ✅」掩蓋未驗項**。

### 13.4 ★★ N2 四項——**全數完成**（`N2-a`／`N2-b`／`N2-c`／`N2-d`）

| 項 | 內容 | 狀態 |
|---|---|---|
| **N2-c** | **監控三支柱截圖**（Grafana／Prometheus／Jaeger／Loki） | ✅ **已執行（2026-10-15，`#A-235`）**——★ 起 `party-service`（真實 Oracle／Kafka／Redis，`SERVER_PORT=8084`）＋ **真實 HTTP 流量**（`GET /api/v1/parties/{partyId}` 200×10／`/actuator/health` 200×10／404×5）→ ★ **4 張截圖皆顯示真實數據**：Prometheus 指標圖（4 序列）／Jaeger **20 軌跡**／Grafana Loki **139 行**日誌／Grafana Prometheus 圖。★ 產出 `docs/08-evidence/N2_監控三支柱截圖.md` |
| **N2-d** | **契約一致性全掃** | ✅ **已執行（2026-10-15，`#A-232`）**——★ 原阻塞（`#A-187` 之 4 處不符）已由 `CR-043` 全數閉合 → **不符 0 處**。見 §13.5 |

> ★★ **併新增 `verify_nfr.py` 之 `monitoring` 證據源（`#A-235`）**：★ 原 `Monitoring`／`監控機制`
> 僅映射 `doc:SAD-006`（**設計已備**）→ ★ N2-c 截圖完成後**矩陣仍為 📄**（★ 同 §13.4.1 之**落檔缺口**）。
> ★ 已新增 `monitoring` 源（★ **fail-closed**：需 `N2_監控三支柱截圖.md` 含
> `<!-- monitoring-evidence: PASS shots=N -->` 標記 **且** `N2-c_*.png` 張數 ≥ N；★ 缺標記／verdict≠PASS／檔不足皆**不通過**）。
> ★★ **矩陣變化：✅ `20` → `22`、📄 `19` → `17`**（`Monitoring`／`監控機制` 由 📄 轉 ✅）。

#### 13.4.1 ★★ 落檔缺口之發現與修補（2026-10-15，`#A-225`）

> ⚠️ **問題**：`verify_nfr.py` 有 `--out` 參數（寫入 `docs/08-evidence/NFR證據矩陣.md`），
> ★ 惟 **N2 批次（10-06）跑工具時未帶 `--out`** → ★ **該檔停在 N1 狀態（10-02）**。
> ★★ 即：**N2 之成果只存在於 stdout，權威落檔未更新**（`TRP-002` 自己明文
> 「勿手改」之檔反而最舊）——★ 違反「文件為單一真實來源」。

| 版本 | ✅ | ❌ | 📄 | ⚠️ |
|---|---:|---:|---:|---:|
| 舊檔（HEAD，10-02，N1） | 13 | 2 | 24 | 21 |
| **新檔（10-15 重跑落檔）** | **20** | **0** | **19** | 21 |

> ★ 舊檔之 **✅13／❌2** 與 §13.3 記載之 N1（`#A-160`）**完全吻合** → 證實未隨 N2 更新。
> ★ **已修補**：`python3 tools/verify_nfr.py --out docs/08-evidence/NFR證據矩陣.md`（09:54）。
>
> ★★ **量測方法教訓**：**`grep -oE "(✅|📄|❌|⚠️)"` 全檔計數 ≠ 統計區數字**——
> 矩陣**表格每列亦含狀態符號**，全檔計數會**重複計數**（實測偏差 ✅+2／❌+2／📄+4／⚠️+4）。
> → ★ **判斷矩陣狀態一律讀「`## 統計` 區**，不可用全檔 grep」。
> ★ **併記**：類似「**檔案時間戳 ≠ 內容新鮮度**」——落檔與否要看**內容統計**，非檔案 mtime。

### 13.5 ★★ N2-d：契約一致性全掃（`#A-232`，2026-10-15）

★ **緣由**：`#A-187` 揭露之 **4 處既有契約不符**（擋住 N2-d）。BEAM PMO 2026-10-15 裁定
「執行 `CR-043 §2.1／§2.2／§2.4` 之建議（修契約）」→ 4 處**全數閉合** → N2-d 方可執行。

| 項 | 方法 | 結果 |
|---|---|---|
| 契約修正 | `tools/gen_openapi.py`（★ 不可手改 YAML）——新增 `ReversalResult`／`OverrideResult` schema ＋ 兩端點回應 `$ref`；`InstallmentPeriod` 補 `principalAmount` | ★ 契約重生 **0 錯誤**（96 端點） |
| 回應併修 | `InstallmentView.PeriodView` ＋ `InstallmentViewAssembler` 補 `principalAmount`（★ 使契約＝回應一致） | ★ `installment-service` **49 測 0 失敗** |
| **契約一致性全掃** | `python3 tools/verify_contract_dto.py` | ★★ **不符 0 處**（原 4 處）；**需確認 0 則**（原 7 則）；**INFO 8 則**（原 14 則）——★ §3.1 之 7 則「需確認」亦已由 `CR-043 §3.1` 結案（見下） |
| 工具自測 | `python3 tools/verify_contract_dto.py --selftest` | ★ **8/8 通過**（含正／負樣本） |

★★ **不符數歷程**：**4 處**（`CR-043` 立時）→ **3 處**（§2.3）→ **0 處**（§2.1／§2.2／§2.4）。

★ **產出**：`docs/08-evidence/N2_契約一致性全掃.md`（執行輸出轉錄；★ 該工具**無 `--out`**）。

★★ **後續（同日）**：BEAM PMO 2026-10-15 裁定「**統一命名差異**」→ **`CR-043 §3.1` 之 7 則全數結案**（見 `CR-043 §10`）：
6 則型別名統一為**實作型別名**（契約側更名；★ 除 #1 改實作側）＋ 1 則移除 stale 端點
（`limit` `cards/{cardId}/limits`；★ 併更正 `SDD-003`／`SDD-006`）。★ **契約重生 95 端點／0 錯誤**；
★ `verify_contract_dto` → **需確認 0 則、INFO 8 則**。★ 併發現並修正 `AuthorizeResponse.checkResults`
之**欄位不符**（巢狀工具盲區）。

⚠️ **如實揭露**：★ 本節**不宣稱「N2-d 全數無懸念」**——★ **INFO 8 則**（請求型別／巢狀視圖）仍在，
惟 INFO **非「不符」**、不影響結論。

★ **併記（量測環境陷阱，2026-10-15 實測）**：`verify_nfr.py` 之 **`deps` 證據需先
`source ops/local/env.sh`**（`JAVA_HOME=21`）——★ **未 source env 直接跑** → `scan_deps.py`
以 **JVM 8** 跑 Gradle → `Gradle requires JVM 17 or later` → deps 記「未執行」→ ★ **矩陣出現假 `❌ 1`**
（★ 實為**環境**問題，非缺陷）。★ **source env 後重跑 → 恢復 ✅20／❌0／📄19／⚠️21**。
★ 教訓：**NFR 量測（含 `--out` 落檔）一律在 cardcore env 內執行**；★ **見到 `❌` 先查是否為環境所致**。

---

## 14. 修訂記錄

| 版本 | 日期 | 修訂內容 |
|---|---|---|
| 1.5 | 2026-10-15 | ★★★ **N2-c 執行完成（`#A-235`）——N2 四項全數完成**：★ 起 `party-service`（真實 Oracle／Kafka／Redis）＋ 真實 HTTP 流量 → ★ **監控三支柱截圖 4 張**（Prometheus 指標圖／Jaeger 20 軌跡／Grafana Loki 139 行／Grafana Prometheus）**皆顯示真實數據**（★ 逐張經真實瀏覽器檢視驗證，非「有畫面就算過」）。★ 產出 `docs/08-evidence/N2_監控三支柱截圖.md`；§13.4 標題改「全數完成」。★ 併記 **Loki `service_name` 恆為 `unknown_service`**（Collector `filelog` 已知限制）——★ 篩選改用 `service_name_extracted`（管線過濾） |
| 1.4 | 2026-10-15 | ★★★ **N2-d 執行完成（`#A-232`）——新增 §13.5**：★ 契約 ↔ 實作**逐端點全掃**（`verify_contract_dto`）——★★ **不符 4 處 → `0` 處**。★ 阻塞解除：`#A-187` 之 4 處既有不符經 **`CR-043`（§2.1／§2.2／§2.3／§2.4）全數閉合**（契約修 2 端點回應型別＋補 `principalAmount`；實作補 `AuthorizeRequest` 三欄接收）。★ 工具自測 **8/8**。★ 產出 `docs/08-evidence/N2_契約一致性全掃.md`。⚠️ **需確認 7 則未結案**（命名／路徑），屬另案裁定。★ **N2 四項現況：a✅／b✅／c⚠️未執行／d✅** |
| 1.3 | 2026-10-15 | ★★ **新增 §13.4.1 落檔缺口之發現與修補（`#A-225`）**：★★ **`verify_nfr.py` 之 `--out` 未被 N2 使用** → ★ **證據矩陣檔停在 N1 狀態（10-02，✅13／❌2）**，★ 而 N2 成果僅存於 stdout → ★ **違反「文件為單一真實來源」**。★ **已重跑落檔**（✅20／❌0／📄19／⚠️21，09:54）。★★ **量測方法教訓**：**全檔 `grep` 狀態符號會重複計數**（矩陣表格每列亦含符號）→ ★ **一律讀「`## 統計` 區**」。⚠️ **待 BEAM PMO 裁定**：★ 建議將「`--out` 必帶」納為 NFR 量測之固定步驟（免再脫節） |
| 1.2 | 2026-10-06 | ★★★ **新增 §13 N2 批次執行結果（`#A-223`／`#A-224`）——N2 前兩項完成**：★★ **證據矩陣 ✅15 → 20；📄 24 → 19**。★ **N2-a 架構邊界檢核**（`#A-223`）：★ **新增工具 `tools/verify_architecture.py`**（零相依、可失敗、`--selftest` 8/8）——**8 項全通過**（容器化 19／19、健康探測 19／19、無狀態 0 處、分層 0 處違規、設定外部化 0 處、呼叫逾時預設 2000/3000/200ms、埠 19 個無重複、DB 身分 17 個無重複）。★★★ **真機反駁本工具自身 2 項缺陷**（★ **A6 偽陽性**：逾時保證在程式碼預設值非逐服務 yml；★★★ **A7 假綠**：埠不在 yml → **空量測卻報 ✅**）→ ★ **「量不到東西必須報無法判定而非 ✅」**。★ **N2-b SSO 五情境**（`#A-224`）：★ **真實 Keycloak ＋ 真實後端**——**9 項全通過**（**無 token→401／帶真 token→200 真實資料 `P001`·王小明／偽造 token→401／refresh→200**）；★ 併為 `verify_sso_pkce.py` 加 `--out` 產出**機器標記 ＋ verdict 之執行紀錄**。★★ **真機反駁我方 1 項**（RAW(16) hex ≠ UUID 字串）。★ **N2-c／N2-d 未執行，如實記錄阻塞** |
| 1.1 | 2026-10-02 | ★ **新增 §11 N1 批次執行結果**（`#A-160`）：JaCoCo 基線（**行 53.7%／分支 46.8%**，未達 80%／70%）；依賴漏洞掃描（**後端 3 CRITICAL＋10 HIGH**、前端 1 HIGH＋3 MODERATE）；**`tools/verify_nfr.py` 證據矩陣**（✅13／❌2／📄24／⚠️21）。★ 併載**工具開發中修正之三個缺陷**（OSV batch 只回 ID、修復版本跨分支混收、初版以「有檔案」當證據＝假綠）。**準出 #1／#7 由「無法判定」變為「已量測且未達」** |
| 1.0 | 2026-10-02 | 初版（BEAM PMO 指示）：建立 **Ａ／Ｂ／Ｃ 三分類法**與判定準則；**60 小節逐項分類**（Ａ 39／Ｂ 13／Ｃ 8；689／137／48 項）；★ **產出「可立即做」清單 8 項（不需新工具）＋ 6 項工具缺口**；與 `TRP-001 §6.2` 之 8 項準出對照；執行順序 N1～N5；五項誠實揭露。★ **關鍵發現**：**覆蓋率從未量測**（`backend` 未配置 JaCoCo）→ 準出 #1 目前**無法判定**；**前端零測試框架** |
