Project

General

Profile

CR #229 » CR-028_hold事件群四項矛盾之化解.md

內容更新:內部稱謂去識別化(2026-10-18) - Redmine Admin, 10/18/2026 05:32 AM

 

CR-028 hold 事件群四項矛盾之化解(CR-027 §5 #1~#4)

項目 內容
文件編號 CR-028
版本 1.0
提出日 2026-10-01
提出者 WorkBuddy AI(開發團隊)
緣起 BEAM PMO 指示「批次 B(hold 事件群)動工前必須先裁定 CR-027 §5 #1~#4,請一一化解,不用急。我不求快,但求精準無誤」。本 CR 即為該四項之化解方案 + 執行紀錄
影響範圍 SAD-002 §3.1/§3.2、SAD-004 §5.2、SDD-006 §4.2、GOV-001 §4.4、SCS-002 §7.6
狀態 ✅ 已化解並執行(文件層);程式碼零影響(見 §5)

1. 化解方法(先查證、再擬案、後動手)

BEAM PMO 要求「精準無誤」,故本次不憑文件互相比較就下結論,而是先取客觀證據:

證據來源 取法
程式碼是否曾實作該事件 全庫搜尋 authorization.hold.
payload 是否實質相同 比對 SDD-006 §4.2 之兩列
權威欄位是否足以支撐 直接查 user_tab_columns(真實 Oracle)

2. 查證結果(四項證據,皆可複驗)

證據 A|authorization.hold.* 全庫程式碼零引用

搜尋 authorization\.hold\. 於 cardcore/ 全庫,命中僅 5 處,全在文件:

位置 內容
SAD-002 §3.1(行 89) authorization 之「事件(發布)」清單
SAD-004 §5.2(行 302/303) 事件清單兩列
SDD-006 §4.2(行 409/410) 事件 payload 兩列
GOV-001 §4.4(行 165) 命名範例(非契約)

→ 零程式引用:AuthorizeUseCase 從未發射此二事件;limit-service 從未訂閱。
→ 故廢除之「程式影響」為零(僅文件需修)。

證據 B|authorization.hold.created.v1 與 limit.hold.created.v1 是同一件事

SDD-006 §4.2 之 authorization.hold.created.v1 payload = holdId, accountId, holdAmount, holdType。
而 SAD-002 §3.2 稱 limit 發布 limit.hold.created.v1——本專案 #A-122 已實作,其 payload(依 SCS-002 §7.6)逐欄相同。

→ 同一語意、兩個前綴;limit.hold.created.v1 從未被登錄於 SDD-006 §4.2(清單漏列)。

證據 C|limit_holds 之權威在 CC_LIM

表 服務 性質
CC_LIM.LIMIT_HOLDS limit-service 權威(SAD-002 §3.2/SCS-002 §8:「本埠為唯一權威出入口」)
CC_AUTH.LIMIT_HOLDS authorization-service 本地投影(V2__read_model.sql 明文:「權威在 CC_LIM.LIMIT_HOLDS」)

→ hold 之事實由 limit 產生;authorization 只能消費,不能發布。

證據 D|兩張 limit_holds 皆有 AUTHORIZATION_ID

表 欄位(實查 user_tab_columns)
CC_LIM.LIMIT_HOLDS ID/ACCOUNT_ID/AUTHORIZATION_ID/HOLD_AMOUNT/RELEASED_AMOUNT/HOLD_TYPE/STATUS/EXPIRES_AT/CREATED_AT/UPDATED_AT/VERSION
CC_AUTH.LIMIT_HOLDS ID/ACCOUNT_ID/AUTHORIZATION_ID/CURRENCY/HOLD_AMOUNT/RELEASED_AMOUNT/STATUS/EXPIRES_AT/CREATED_AT/UPDATED_AT/VERSION

→ limit 有能力提供 authorizationId;authorization 需要它以維護本地投影。


3. 逐項化解

#1 hold 事件之方向與權威 → 定案:廢除 authorization.hold.*,只保留 limit.hold.*

項目 內容
矛盾 SAD-002 §3.1 稱 authorization 發布 authorization.hold.created.v1/.released.v1;§3.2 稱 limit 發布 limit.hold.created.v1/.released.v1——同一事實兩個生產者
證據 A(零程式引用)、B(payload 逐欄相同)、C(權威在 CC_LIM)
定案 (a) 廢除 authorization.hold.created.v1/authorization.hold.released.v1;hold 事件一律由 limit-service 發布(limit.hold.created.v1/limit.hold.released.v1)
理由 ① authorization.hold.created.v1 與 limit.hold.created.v1 是同一件事——保留兩個名字必然造成「同一事實兩則事件」之重複消費;② authorization 不是 hold 之權威(CC_LIM.LIMIT_HOLDS 才是),由其發布「佔用已建立」是事實歸屬錯誤;③ authorization 對 limit 之佔用請求是同步 API(POST /limit-holds)——那是命令,不是事件(GOV-001 §4.4:事件為過去式既成事實)
⚠️ 一併釐清 authorization.hold.released.v1 之 payload 為 holdId, releasedAmount, reason(含 reason),與 limit.hold.released.v1(holdId, accountId, releasedAmount)不同欄。惟「帶原因」正顯示其為命令(「請釋放,原因為 X」)——原因屬請求參數,非事件事實。故一併廢除
影響 文件 4 處(SAD-002 §3.1、SAD-004 §5.2、SDD-006 §4.2、GOV-001 §4.4 範例);程式 0 處

#2 authorization 訂閱清單 → 定案:以 SAD-002 為準,auth 訂閱 limit.hold.created.v1

項目 內容
矛盾 SAD-002 §3.1 之 auth 訂閱清單含 limit.hold.created.v1;SAD-004 §5.2 之事件清單無此事件(僅有 limit.hold.released.v1)
證據 C(auth 有本地投影 CC_AUTH.LIMIT_HOLDS,需被餵養)
定案 以 SAD-002 為準——auth 訂閱 limit.hold.created.v1;並補登至 SAD-004 §5.2
理由 若只訂閱 released 而不知 created,消費者會「釋放一筆不存在的佔用」——本地投影將永遠缺列(與 card_status_caches 曾恆空之缺陷同型)

#3 limit.hold.released.v1 之消費者 → 定案:消費者為 authorization(與 #2 同批處理)

項目 內容
矛盾 SAD-004 §5.2 載消費者=authorization;SAD-002 §3.1 之 auth 訂閱清單未含它
定案 補進 SAD-002 §3.1——auth 訂閱 limit.hold.created.v1 與 limit.hold.released.v1
理由 二者為同一本地投影之生命週期(建立→釋放),拆開訂閱必造成投影狀態落後(如 released_amount 永不更新)

#4 limit.hold.created.v1 payload 缺 authorizationId → 定案:補為「可選」欄位,不升版

項目 內容
矛盾 SDD-006 §4.2 之 authorization.hold.created.v1 payload 為 holdId, accountId, holdAmount, holdType——無 authorizationId,惟 authorization 之本地投影有 AUTHORIZATION_ID 欄位
證據 D(兩張表皆有該欄位)
定案 (b) 補 authorizationId 為可選欄位(SAD-004 §5.3:「新增可選欄位 → 不升版」);併登錄 limit.hold.created.v1 之完整 payload(含 authorizationId)
理由 ① limit 有能力提供(權威表有該欄);② authorization 需要它(否則無法把 hold 對應回自己的授權);③ 為可選——stand-in 等無對應授權之情境可為 null,故不升 v2、無雙軌成本
影響 SCS-002 §7.6(改「刻意不納入」→「可選」)+ LimitEventFactory(下一輪實作,屬批次 B)

4. 需同步修訂之文件(本 CR 已執行)

# 文件 修訂
1 SAD-002 §3.1 「事件(發布)」移除 authorization.hold.created.v1/.released.v1;「事件(訂閱)」補 limit.hold.created.v1、limit.hold.released.v1
2 SAD-002 §3.2 「事件(發布)」補 limit.hold.created.v1(原已列 .released.v1)
3 SAD-004 §5.2 刪兩列 authorization.hold.*;補 limit.hold.created.v1 一列(生產者 limit、消費者 authorization)
4 SDD-006 §4.2 刪兩列 authorization.hold.*;補 limit.hold.created.v1(含 authorizationId 可選)
5 GOV-001 §4.4 命名範例 authorization.hold.created.v1 → limit.hold.created.v1
6 SCS-002 §7.6 authorizationId 由「刻意不納入」改為「可選欄位」;移除「SAD-002 §3.1 矛盾待裁定」之註記

5. 對程式碼之影響:零

項目 說明
authorization-service 無——從未發射 authorization.hold.*(證據 A)
limit-service 已實作 limit.hold.created.v1/limit.hold.released.v1(#A-122)→ 本 CR 不動程式;僅 authorizationId 之補入屬批次 B
其他服務 無

⚠️ 故本 CR 無需重編譯、無需真機驗證——這是文件層之化解。
(符合 GOV-003 條件 9:「先有規格、才寫程式」——此處連程式都不需改。)


6. 化解後之批次 B 藍圖(供下一輪動工)

步驟 內容
① 規格先行 SCS-002 §7.6 補 authorizationId(已於本 CR 完成);SCS-001 §7.15 新增「佔用事件消費」
② 生產端 LimitEventFactory.holdCreatedEnvelope 補 authorizationId(可選,由 LimitApplicationService.hold 傳入)
③ 消費端 authorization-service 消費 cc.limit.limit.hold.created/.released → upsert 本地 limit_holds(冪等+亂序,沿用 consumed_events)
④ 真機 建立佔用 → limit_holds 本地投影落列;部分釋放 → released_amount 更新

7. 未竟(誠實揭露)

  1. 本 CR 未動任何程式——批次 B 之實作(含 authorizationId 之補入)尚待動工。
  2. limit.hold.created.v1 之消費者尚未實作 → 現階段 CC_AUTH.LIMIT_HOLDS 仍無餵養者(僅 stand-in 路徑寫入)。
  3. CR-027 §5 其餘 8 項(#5~#12)仍待裁定——其中 #5(事件清單權威) 與本 CR 相關:
    本 CR 已將 limit.hold.created.v1 補登至 SAD-004 §5.2,惟兩份清單是否合併為單一權威仍待 BEAM PMO 裁定。

8. 修訂記錄

版本 說明
1.0 初版:hold 事件群四項矛盾之化解——先取四項客觀證據(零程式引用/payload 逐欄相同/權威在 CC_LIM/兩表皆有 AUTHORIZATION_ID),再逐項定案;已執行 6 份文件之同步修訂;程式碼零影響
    (1-1/1)