CR #222 » CR-021_authorization-service三支契約端點完全未實作.md
CR-021 authorization-service 三支契約端點完全未實作,與 SDD-007 §5.1.2 桶 A 之盤點錯誤
| 項目 | 內容 |
|---|---|
| 文件編號 | CR-021 |
| 版本 | 1.0 |
| 提出日 | 2026-09-23 |
| 提出者 | WorkBuddy AI(開發團隊) |
| 緣起 |
C-14 桶 A 續作(授權策略檢核/離線授權與代授權/沖正機制三頁)之動工前查證:欲依 SDD-007 §5.1.2 桶 A 施作時,發現其依賴之三支端點程式完全不存在
|
| 影響範圍 |
contracts/openapi/authorization-service.yaml;SDD-007 §5.1.2(桶 A 盤點);CSP-001 §7.1(G-8 檢查點);tools/verify_contract_dto.py(新增端點存在性檢查) |
| 關聯前例 |
CR-020 F1(契約宣告欄位、實作未接收)——同為「契約有、實作無」,本 CR 在端點層級;CR-016 §8(回應型別不符) |
1. 問題定性:契約宣告了消費端打不到的端點
contracts/openapi/authorization-service.yaml 宣告 5 個端點,
而實作(AuthorizationController)只有 3 個:
| # | 契約端點 | 實作 | 判定 |
|---|---|---|---|
| 1 | POST /api/v1/authorizations |
✅ 有 | — |
| 2 | GET /api/v1/authorizations |
✅ 有 | — |
| 3 | GET /api/v1/authorizations/{authNo} |
✅ 有 | — |
| 4 | POST /api/v1/authorizations/{authId}/reversals |
❌ 無 | 未實作 |
| 5 | POST /api/v1/authorizations/{authId}/advices |
❌ 無 | 未實作 |
| 6 | GET /api/v1/authorizations/{authId}/check-results |
❌ 無 | 未實作 |
實測方式:全服務搜尋 RestController 僅得 1 支 AuthorizationController;
以 reversals/advices/check-results/CheckResult/ReversalRequest
為關鍵字搜尋 src/main/java 結果為 0(連 DTO 都沒有)。
⚠️ 契約對這三支還詳列了 requestBody schema、13 項檢核明細說明、錯誤碼
(如「已沖正回CC-AUTH-3002(409)」「PARTIAL必帶amount≤原金額」),
消費端依契約開發將全部得到 404。
2. 連帶發現:SDD-007 §5.1.2 桶 A 之盤點方法錯誤(我方缺失)
§5.1.2(2026-09-23,SDD-007 1.10)當初之盤點方式為
「頁面所需功能 ↔ 該服務端點語意」做語意匹配,
但未驗證「該端點在契約與實作中確實存在」。
結果把下列三頁誤列為「桶 A 可立即實作」:
| 頁面 | 路徑 | 依賴端點 | 實況 |
|---|---|---|---|
| 授權策略檢核 | /auth/policy |
GET /authorizations/{authId}/check-results |
端點不存在 |
| 離線授權與代授權 | /auth/stip |
POST /authorizations/{authId}/advices |
端點不存在 |
| 沖正機制 | /switch/auth/reversal |
POST /authorizations/{authId}/reversals |
端點不存在 |
★ 教訓(已制度化,見 §4):
「服務有端點」≠「該頁有對應端點」——這是
§5.1.2原本要解決的問題;
但本次暴露出更前一層的漏洞:
「契約有端點」≠「實作有端點」。
盤點時若只查契約(或只做語意匹配),即會把「不存在的端點」當成可用。
3. 併發現:limit-service 之契約/實作路徑寫法差異(1 則,需確認)
| 契約 | 實作 | 判定 |
|---|---|---|
GET /api/v1/cards/{cardId}/limits |
GET /api/v1/accounts/{accountId}/limits |
路徑寫法差異(同 verb、同末端段 limits) |
二者資源識別維度不同(cardId vs accountId),非單純別名——
若消費端依契約以 cardId 查額度將 404。待確認:係修契約(改為 accounts/{accountId})
或修實作(補一支 by-card 路徑)。
4. 制度化:G-8 新增「端點存在性」檢查面(不再只靠人工)
tools/verify_contract_dto.py 原已能偵測「契約有端點、Controller 無對應方法」,
但僅歸入 infos(不影響結論)→ 此類缺陷被靜默放過。
本期改為二分級,並納入結論:
| 情形 | 歸類 | 訊息 |
|---|---|---|
| 同服務無任何「同 verb 且同末端段」之實作路徑 | hits(確定未實作) |
「消費端依契約呼叫將 404」 |
| 同服務有「同 verb 且同末端段」之其他路徑 | warns(疑似路徑寫法差異) |
列出候選路徑,請人工確認 |
為何要分級:直接全部升為 hits 會對 limit-service 這類「路徑寫法差異」
產生偽陽性;本專案對偽陽性零容忍(會侵蝕工具可信度),故先比對末端段。
回測(--selftest)由 4/4 擴充為 6/6,新增兩個人工樣本:
-
EXPECT-HIT-missing-endpoint:契約有、Controller 完全無 → 必須命中 -
EXPECT-WARN-path-alias:契約cards/{cardId}/limitsvs 實作accounts/{accountId}/limits
→ 必須為 warn 且不得為 hit(證明不會偽陽性)
5. 待裁定
| # | 議題 | 選項 |
|---|---|---|
| 1 | 三支未實作端點 |
(a) 本期補實作(建議——契約已詳載語意,且 SDD-005/SCS 應有對應設計);(b) 自契約移除並加註「本期不提供」 |
| 2 | 三頁之處置 | 移至桶 C(待後端)——不造空殼(客戶硬性要求) |
| 3 |
limit-service 路徑差異 |
修契約(改 accounts/{accountId})/修實作(補 by-card) |
我方建議:先做 (1)-(a)。理由:契約對這三支之語意已相當完整
(13 項檢核明細、FULL/PARTIAL沖正、強制授權軌跡),
且「沖正」在信用卡業務為必要功能(SDD-005 §3已有佔用狀態機之
HELD --取消/沖正--> RELEASED轉換),不是可省略的項目。
若採 (b),等於宣告「本期不做沖正」,恐與 RFP 需求不符。
6. 誠實揭露
-
本 CR 之盤點錯誤源自我方(
§5.1.2於SDD-0071.10 建立時未驗證端點存在),
非既有程式缺陷——程式缺陷(三支未實作)則是本次查證所發現。 - 尚未動工:本輪僅查證與制度化,未開始撰寫這三頁(避免造空殼)。
-
未驗證範圍:
advices之語意(契約載「人工授權/強制授權(Override)」)
與頁面名「離線授權與代授權(STIP)」是否為同一件事,尚待確認
——契約描述回APPROVED/STANDIN,似同時涵蓋兩者,但語意不完全相同,
頁面命名與歸屬建議於補實作時一併釐清。
7. 執行結果(2026-09-23,BEAM PMO「請繼續」→ 採 §5 (a) 補實作)
| 端點 | 狀態 | 真機驗證 |
|---|---|---|
GET …/{authNo}/check-results |
✅ 已實作 | 回契約形狀陣列(AMOUNT/CURRENCY/CARD_STATUS/… 逐項 PASS+reasonCode);併修正契約陣列性(原誤宣告單一物件);查無 → CC-AUTH-4040/404(初版 ResponseStatusException 落兜底 500,已改) |
POST …/{authNo}/reversals |
✅ 已實作(** Stand-in 佔用除外**) | 實測發現 runtime 掛載 StandInLimitPort(種子授權皆為 Stand-in 本地佔用)→ 初版 500,已改為明確業務拒絕(CC-AUTH-3001/422)。FULL 沖正 happy path 待「Stand-in 佔用沖正設計」裁定後方可真機驗證
|
POST …/{authNo}/advices |
⬜ 語意待裁定(SCS-001 §7.7:(a) 後送 vs (b) 人工覆核) |
未實作(不猜語意);/auth/stip 頁續留桶 C |
落地:V5__auth_reversals.sql(AUTH_REVERSALS+AUTHORIZATIONS.REVERSED_AT);LimitPort.release(Remote 轉呼 limit-service/StandIn、Jdbc fail-loud);ReversalService(已沖正→CC-AUTH-3002、查無→CC-AUTH-4040、PARTIAL≤holdAmount、釋放+紀錄同交易;決策欄不修改)。SCS-001 → 1.1、SDD-006 → 1.9(CC-AUTH-4040,123 碼)。
誠實揭露:①查無授權初版 500(ResponseStatusException 未被 handler 映射)→ 已改 CC-AUTH-4040,連既有明細端點一併修正(同服務不得兩套真相);②檢核視圖初版誤沿用 AuthorizeResponse.CheckResultView(新落差),真機實測後改為契約形狀。
8. 修訂記錄
| 版本 | 日期 | 修訂內容 |
|---|---|---|
| 1.1 | 2026-09-23 | BEAM PMO「請繼續」→ 採 §5 (a) 補實作:check-results ✅/reversals ✅(** Stand-in 佔用除外**,待裁定)/advices ⬜(§7.7 兩語意待裁定)。新增 §7 執行結果(含兩項誠實揭露)。SCS-001 → 1.1、SDD-006 → 1.9、HANDOVER → 1.73(#A-95) |
| 1.0 | 2026-09-23 | 初版:authorization-service 三支契約端點完全未實作之實測證據;SDD-007 §5.1.2 桶 A 盤點方法錯誤之更正;limit-service 路徑寫法差異;tools/verify_contract_dto.py 新增「端點存在性」檢查(二分級、回測 6/6) |