# CR-022　`advices` 端點語意之三案對照與契約修訂請求

| 項目 | 內容 |
|---|---|
| 文件編號 | CR-022 |
| 版本 | **1.0** |
| 提出日 | 2026-09-24 |
| 提出者 | WorkBuddy AI（開發團隊） |
| 緣起 | `CR-021` 補實作三支端點時，`advices` 因**語意不明**未實作（`SCS-001 §7.7`）。BEAM PMO 指示「整理兩方案對照表以供裁定」；查證後**發現第三種讀法**，一併列入 |
| 影響範圍 | `contracts/openapi/authorization-service.yaml`（`advices` 端點）；`SCS-001 §7.7`；`SDD-007 §5.4.23`（`/auth/stip` 頁，待裁定後補） |
| 狀態 | ✅ **已裁定（2026-09-24，BEAM PMO）：採 (A) 後送**——與原型模組 9 之 L2「待補送佇列／補送結果」同源、可重用既有 `StandInUploadService`，並使 Stand-in 生命週期閉環（佔用→上送→沖正→後送）。**(C) 列後續**（前置缺口大：`REFERRAL` 零產生點、風控檢核未實作）；**(B) 不建議**（body／回應解釋不通＋人工強制核准繞過風控）。**已實作並真機驗證**，見 `SCS-001 §7.7`（(A) 後送）、`§7.7.1`（`standin_flag` 判定依據）、`§7.8`（人工／強制授權） |

---

## 1. 契約原文（逐欄位拆解）

```yaml
POST /api/v1/authorizations/{authId}/advices
  summary:     人工授權與強制授權
  description: 人工授權 / 強制授權（Override）。須具 OVERRIDE 權限，留審核軌跡；回 APPROVED/STANDIN。
  path param:  {authId}        # 無 description
  headers:     X-Channel、X-Idempotency-Key（皆必要）
  requestBody: AuthorizeRequest（完整授權請求：stan/cardNo/txType/amount/currency/mcc/merchantId/txTime…）
  response:    201 AuthorizeResponse（含 checkResults／holdId／holdAmount／availableLimit）
```

### ★ 契約的內在矛盾（本 CR 的核心）

| 欄位 | 指向的語意 | 證據 |
|---|---|---|
| `summary`＋`description` | **人工／強制授權（Override）**——由具權限者介入核決 | 字面明文；且要求 `OVERRIDE` 權限 |
| `path` `{authId}` | 對象是**既有的一筆授權** | 路徑掛在既有授權之下 |
| `requestBody` = 完整 `AuthorizeRequest` | **重新送一次完整交易請求** | 若僅「改判決策」，只需「決策＋理由＋覆核人」即可，無須卡號／金額／MCC |
| `response` = `AuthorizeResponse`（含 `checkResults`／`holdId`） | **會跑檢核並佔額** | 純改判決策不會產生新的檢核明細與佔用 |

→ **前兩列與後兩列指向不同的東西**。任一案都無法同時滿足四列，**故無論選哪一案，契約都必須修訂**（見 §5）。

---

## 2. 三案對照表

> ⚠️ **(A)／(B) 為 BEAM PMO 原指示之兩案；(C) 為本次查證後新增之第三案**（理由見 §3）。

| 對照維度 | **(A) 後送授權通知（Advice）** | **(B) 人工覆核（Override 改判）** | **(C) 人工／強制授權（對轉人工交易核決）** |
|---|---|---|---|
| **一句話語意** | 離線／Stand-in 完成之交易，事後把授權補送進核心 | 對**既有**授權之決策做人工改判（如 `DECLINED`→`APPROVED`） | 交易被**轉人工**（`REFERRAL`）後，由授權中心人員核決（含強制核准） |
| **契約 `summary`／`description`** | ❌ **不符**——字面是「人工／強制授權」，非「後送」 | 🟡 部分符合（「Override」），但「人工／強制**授權**」語意偏新授權 | ✅ **最符合**——字面直指人工／強制授權 |
| **契約 `{authId}` 路徑** | 🟡 可解釋為「該筆離線授權之本地參照」 | ✅ 符合（就是既有授權） | ✅ 符合（被轉人工的那筆授權） |
| **契約 `requestBody`（完整請求）** | ✅ 符合（後送本就要帶原始交易資料） | ❌ **不符**（改判不需卡號／金額／MCC） | ✅ 符合（核決時重送交易資料以完成檢核與佔額） |
| **契約回應（含 `checkResults`／`holdId`）** | ✅ 符合（補送會跑檢核與佔額） | ❌ **不符**（改判不會產生新檢核明細） | ✅ 符合（核決會跑檢核與佔額） |
| **原型模組 9 之 L2** | ✅ **高度吻合**——L2 明列「Stand-in 獨立授權：**開關門檻／超時代行／待補送佇列／補送結果**」，且 `SDD-007 §5.1.1` 已判定此 L2 **由「離線授權與代授權（STIP）」涵蓋** | ❌ 無對應 L2 | 🟡 部分——「超時代行」沾到邊，但「待補送佇列／補送結果」未涵蓋 |
| **既有程式基礎（可重用度）** | ✅ **已有一半**：`StandInUploadService.uploadPending()`＋`findPendingStandIn()`＋`markStandInUploaded()`＋`StandInUploadScheduler`＋`standin_flag`（`SCS-001 §7.4`） | ❌ 無（全新流程） | ❌ 無（全新流程） |
| **前置缺口** | 需釐清**與既有排程上送之分工**（避免兩條路徑打架：手動 vs 定時） | **無 `REFERRAL` 產生點** → 只能對 `DECLINED` 改判 → **等於繞過風控** | ⚠️ **無 `REFERRAL` 產生點**（實測：全服務僅 enum 宣告、**零產生處**）；且「何時該轉人工」之判斷依據（`RISK`／`DAILY_LIMIT`／`VELOCITY` 等 `CheckCode`）**未實作、無資料模型** |
| **資料模型影響** | 小——既有 `standin_flag`／`standin_upload_at` 已足；可能加「後送來源」標記 | 中——需 `auth_overrides`（決策、理由、覆核人、時間） | 中——需 `auth_overrides` ＋ **`REFERRAL` 產生規則**（可能需新表或參數） |
| **實作工作量** | **小**（端點＝既有上送服務之介面化＋查詢補送結果） | 中 | **大**（需先補轉人工規則之資料模型） |
| **主要風險** | 與排程重複上送（**須以冪等鍵／狀態守門**）；契約需改寫 summary | **風控繞過**（人工可強制核准任何拒絕件）；且無法解釋回應型別 | 前置缺口大，易變成「先做半套」 |
| **業務價值** | 高——直接對應原型明列功能；且**沖正機制（#A-96）已完成**，Stand-in 生命週期（佔用→上送→沖正）僅缺此段 | 低—中（且方向可疑） | 中—高（實務必要），但**須先有轉人工規則** |
| **技術連續性** | ✅ 最高——與剛完成之 Stand-in 佔用／沖正同一血脈 | ❌ 無 | 🟡 部分 |

---

## 3. 為何新增 (C) 案

不是為了擴大範圍，而是查證契約原文後發現：**只有 (C) 能同時解釋契約的四個欄位**（`summary` 說人工／強制授權、路徑指向既有授權、body 是完整請求、回應含檢核明細與佔額）。

**(A) 的弱點**：機制與既有 Stand-in 同源、實作最省，但**與契約 `summary`「人工授權與強制授權」直接衝突**——若採 (A)，等於承認契約的 summary／description 寫錯了。
**(B) 的弱點**：最不符契約（body 與回應都解釋不通），且業務上危險（人工強制核准繞過風控）。
**(C) 的弱點**：**前置缺口最大**——`REFERRAL` 目前零產生點，而「何時轉人工」的判斷依據（風控類 `CheckCode`）尚未實作、無資料模型（`CheckCode.isImplemented()=false`）。

---

## 4. 三案之共通事實（已查證）

1. **`SDD-005` 完全沒有** advice／STIP／代授權相關狀態機 → **三案皆須新增規格**，無既有狀態機可依。
2. **`REFERRAL` 決策存在於 `AuthDecision` enum，但全服務零產生處**（`grep` 僅得 enum 宣告）→ 目前**沒有任何「轉人工」的交易**可被核決。
3. **`STANDIN` 決策之來源已明確**（`SCS-001 §7.4`）：`HoldResult.standIn=true`（額度服務失敗降級）→ `standin_flag=1`。
4. **`CheckCode` 15 項中僅 6 項具資料來源**——`RISK`／`DAILY_LIMIT`／`GEO`／`VELOCITY`／`BLACKLIST` 皆未實作（`CSP-001 §8 B2` 不做假檢核）→ (C) 之「轉人工判斷依據」**目前無從實作**。

---

## 5. 無論選哪一案，都必須做的契約修訂

| # | 修訂項 | 說明 |
|---|---|---|
| 1 | **`summary`／`description` 對齊** | 目前 summary 說「人工授權與強制授權」；若採 (A) 須改為「後送授權通知」；若採 (C) 須補「對 `REFERRAL` 之核決」 |
| 2 | **路徑參數命名與語意** | `{authId}` 應明確為 `{authNo}`（業務代碼，與同服務另兩端點一致）並補 `description`；若採 (A) 且對象非既有授權，路徑本身可能須改（**破壞性**，需評估） |
| 3 | **`OVERRIDE` 權限語意** | 僅 (B)／(C) 需要；(A) 不需要 → 須明確寫入或移除 |
| 4 | **回應碼** | 契約為 **201**；但 (B)／(C) 對既有授權之操作語意上宜為 **200**（(A) 產生新紀錄則 201 合理） |
| 5 | **錯誤碼** | 三案皆需明列：查無授權（`CC-AUTH-4040`）、狀態不允許（`CC-AUTH-3001`／`3002`）、無權限（`CC-AUTH-4003`? 待確認） |

---

## 6. 我方建議

**建議採 (A)，並將 (C) 登記為後續項（待風控規則資料模型補齊）。**

理由：
1. **(A) 有既有基礎可重用**（`StandInUploadService`＋待補送佇列），且**沖正機制剛完成**（#A-96）——採 (A) 可讓 **Stand-in 生命週期閉環**：佔用 → 上送 → 沖正 → **後送查詢**，四段齊備。
2. **(A) 直接對應原型模組 9 明列的 L2**（待補送佇列／補送結果）——這是**客戶原型已寫的功能**，交付價值明確。
3. **(C) 雖最貼合契約字面，但前置缺口最大**（`REFERRAL` 零產生點＋風控檢核未實作）→ 若現在做，極可能做成半套（這正是 BEAM PMO 最在意的「邊想邊做」）。
4. **(B) 不建議**：body 與回應都解釋不通，且人工強制核准繞過風控，業務風險高。

⚠️ **採 (A) 之代價**：須改契約 `summary`／`description`（承認原描述寫錯），並明確 (A) 之端點與既有**排程上送**的分工（建議：端點供「手動觸發＋查詢補送結果」，排程續行定時上送，兩者共用同一冪等守門）。

---

## 7. 待裁定清單

| # | 議題 | 選項 |
|---|---|---|
| 1 | `advices` 語意 | **(A) 後送**（我方建議）／**(B) 人工覆核**／**(C) 對轉人工核決** |
| 2 | 若採 (A)：與排程上送之分工 | 端點＝手動觸發＋查詢／端點僅查詢（觸發仍由排程）／端點取代排程 |
| 3 | 若採 (C)：`REFERRAL` 產生規則 | 待風控資料模型補齊後另立 CR，或本期以參數化門檻先行 |
| 4 | 回應碼 201 vs 200 | 依所選方案修訂契約 |

---

## 8. 誠實揭露

1. 本 CR **未動任何程式**——`advices` 端點仍未實作（`SCS-001 §7.7` 載明「裁定前不實作」）。
2. §2 對照表之「契約自洽性」判定，係逐欄位比對契約原文所得；**屬我方解讀**，若與 RFP／客戶原意不同，請以 BEAM PMO 之判斷為準。
3. **未查證項**：RFP（`BEAM_核心現代化_信用卡核心_RFP_FR_*.xlsx`）中是否有人工授權／STIP 之明文 FR 編號——本次未查（該檔為 xlsx，未納入本次查證範圍）。**若需以 RFP 為權威依據，請指示，我再查。**

---

## 9. 修訂記錄

| 版本 | 日期 | 修訂內容 |
|---|---|---|
| 1.0 | 2026-09-24 | 初版：`advices` 端點語意之三案對照（原兩案 (A)/(B)＋查證後新增 (C)）；契約內在矛盾之逐欄位證據；三案共通事實（`SDD-005` 無狀態機、`REFERRAL` 零產生點、風控檢核未實作）；契約修訂清單；建議採 (A) 並將 (C) 列後續 |
