# SDD-000　設計總覽與通用規範

| 項目 | 內容 |
|---|---|
| 文件編號 | SDD-000 |
| 版本 | 1.0 |
| 狀態 | 已核定 |
| 撰寫者 | SD |
| 審查者 | SA / TL |
| 對應需求 | 全案設計之共通規範 |

---

## 1. 本文件之定位

`SDD-001 ~ SDD-007` 定義本系統之細部設計。本文件定義**跨設計文件之共通規範**：
分層職責、命名、通用模式、交易邊界、錯誤處理與擴充機制。
**任一設計文件與本文件衝突者，以本文件為準。**

| 文件 | 內容 |
|---|---|
| SDD-001 | 領域模型與 ER-Diagram（含可落地 DDL） |
| SDD-002 | DFD 與流程分解 |
| SDD-003 | Sequence Diagrams（關鍵情境） |
| SDD-004 | Conflict Handling 與一致性設計 |
| SDD-005 | 狀態機設計 |
| SDD-006 | API Contract（OpenAPI 3.1） |
| SDD-007 | WebUI 設計規範 |

---

## 2. 分層職責

| 層 | 目錄 | 職責 | 可依賴 | 禁止 |
|---|---|---|---|---|
| 介面層 | `interfaces/` | 接收請求、驗證格式、轉換為命令、回應 | `application/`、`domain/` | 業務規則 |
| 應用層 | `application/` | 用例編排、交易邊界、埠呼叫 | `domain/` | 直接存取資料庫 |
| 領域層 | `domain/` | 業務規則、不變式、狀態轉換 | 僅標準函式庫 | 框架、ORM、HTTP、日誌 |
| 基礎層 | `infrastructure/` | 持久化、事件發布、外部適配 | `application/`（埠）、`domain/` | 業務規則 |

### 2.1 各層產出物對照

| 層 | 主要產出物 |
|---|---|
| `interfaces/` | Controller、Request/Response DTO、Event Consumer、Mapper |
| `application/` | UseCase（Command Handler）、Query Handler、Port 介面、DTO |
| `domain/` | Aggregate、Entity、Value Object、Domain Service、Domain Event、Specification |
| `infrastructure/` | Repository 實作、Outbox、Publisher、外部 Gateway、Migration |

---

## 3. 命名規範

| 元素 | 規範 | 範例 |
|---|---|---|
| 聚合根 | 業務名詞單數，PascalCase | `Authorization`、`CreditLimit` |
| 實體 | 單數，PascalCase | `AuthHold`、`SubAccount` |
| 值物件 | 單數，PascalCase；**不可變** | `Money`、`CardNumber`、`LimitAmount` |
| 領域服務 | 動詞＋名詞，PascalCase | `LimitCheckService`、`InterestCalculator` |
| 命令 | 祈使句＋Command | `AuthorizeTransactionCommand` |
| 查詢 | 名詞＋Query | `GetAvailableLimitQuery` |
| 事件 | 過去式＋Event | `AuthorizationApprovedEvent` |
| 用例 | 命令／查詢＋Handler | `AuthorizeTransactionHandler` |
| 埠 | 名詞＋Port | `AuthorizationRepositoryPort` |
| 適配器 | 技術＋Adapter | `PostgresAuthorizationAdapter` |
| 規格 | 名詞＋Specification | `SpecialLimitApplicableSpecification` |
| 錯誤碼 | `CC-<SVC>-<NNNN>` | `CC-AUTH-1001` |

---

## 4. 通用設計模式

### 4.1 交易邊界（Unit of Work）

**原則**：**一個用例 = 一個交易邊界 = 一個聚合的異動**。

```mermaid
flowchart TD
  A["用例開始"] --> B["開啟交易"]
  B --> C["載入聚合"]
  C --> D["執行領域行為"]
  D --> E["驗證不變式"]
  E --> F["持久化聚合"]
  F --> G["寫入 Outbox 事件"]
  G --> H["提交交易"]
  H --> I["交易後發布事件"]
  E -->|"不變式違反"| X["回滾並回報錯誤"]
  F -->|"樂觀鎖衝突"| X
  G --> X
```

**規則**
| 編號 | 規則 |
|---|---|
| TX-01 | 一個交易內**僅異動一個聚合**（跨聚合以事件最終一致） |
| TX-02 | 領域事件與聚合異動**同一交易**寫入 Outbox |
| TX-03 | 外部呼叫**不得**置於交易內（除必要之即時檢核，且須設逾時） |
| TX-04 | 交易內**不得**有長時間操作（批次、檔案） |
| TX-05 | 交易後才發布事件（避免事件早於資料提交） |

### 4.2 冪等（Idempotency）

```mermaid
flowchart TD
  A["寫入請求"] --> B{"是否帶冪等鍵"}
  B -->|"否"| E["拒絕：400 缺少冪等鍵"]
  B -->|"是"| C{"冪等鍵是否已存在"}
  C -->|"是，且請求指紋相同"| D["回傳前次結果（200／201）"]
  C -->|"是，但指紋不同"| F["拒絕：409 冪等鍵衝突"]
  C -->|"否"| G["執行業務邏輯"]
  G --> H["寫入結果與冪等鍵（同一交易）"]
  H --> I["回傳結果"]
```

| 規則 | 說明 |
|---|---|
| ID-01 | 所有寫入端點須帶 `X-Idempotency-Key` |
| ID-02 | 冪等鍵保存期限 ≥ 24 小時（授權類 ≥ 14 天） |
| ID-03 | 同鍵同指紋 → 回傳前次結果，不重複執行 |
| ID-04 | 同鍵異指紋 → 409 衝突 |
| ID-05 | 業務層另有自然冪等鍵（如請款之 `卡號+授權碼+日期+金額`） |

### 4.3 樂觀鎖（Optimistic Locking）

| 規則 | 說明 |
|---|---|
| OL-01 | 所有可異動聚合含 `version` 欄位 |
| OL-02 | 更新條件含 `WHERE id = ? AND version = ?` |
| OL-03 | 影響筆數為 0 → 拋出 `ConcurrencyConflictError` |
| OL-04 | 授權熱路徑衝突採**重試 3 次**（指數退避），仍失敗則拒絕交易 |
| OL-05 | 額度扣減採**條件更新**（`available >= amount`）避免超額 |

### 4.4 Outbox（可靠事件發布）

| 規則 | 說明 |
|---|---|
| OB-01 | 事件寫入 `outbox` 表，與聚合異動同一交易 |
| OB-02 | 背景工作者輪詢未發布事件並發送至 Kafka |
| OB-03 | 發布成功後標記 `published_at`（**不刪除**，保留供稽核） |
| OB-04 | 消費者以 `event_id` 冪等 |
| OB-05 | Outbox 表須有 `(published_at, created_at)` 索引 |

### 4.5 補償（Saga）

| 樣式 | 使用情境 | 實作 |
|---|---|---|
| 編排式（Orchestration） | 步驟少、需明確控制（如分期建立） | 由 Saga 協調者驅動 |
| 協同式（Choreography） | 步驟多、事件驅動（如帳務流程） | 各服務監聽事件自行反應 |

詳見 `SDD-004 §4`。

### 4.6 規格模式（Specification）

複雜業務條件（如授權檢核 13 大項）以規格物件組合，**不得**以 if-else 硬寫。

| 規則 | 說明 |
|---|---|
| SP-01 | 每個檢核項為一個 `Specification` 實作 |
| SP-02 | 檢核項之啟用與順序由參數決定 |
| SP-03 | 規格回傳「通過／不通過 + 原因碼」 |
| SP-04 | 規格須可獨立單元測試 |

### 4.7 領域事件

| 規則 | 說明 |
|---|---|
| DE-01 | 事件為**過去式**命名 |
| DE-02 | 事件含 `aggregateId`、`sequenceNo`、`occurredAt` |
| DE-03 | 事件為**不可變**（immutable） |
| DE-04 | 事件僅包含下游需要之欄位（避免洩露內部結構） |
| DE-05 | 事件不得含個資明文（卡號須遮罩或 Token） |

---

## 5. 錯誤處理原則

| 原則 | 說明 |
|---|---|
| ER-01 | 領域層以**例外**表達不變式違反；例外須攜帶錯誤碼 |
| ER-02 | 應用層將例外轉為結果物件，介面層轉為 HTTP 回應 |
| ER-03 | **不得吞例外**：catch 後必須重拋、記錄或補償（`GOV-003 §6.1`） |
| ER-04 | 錯誤訊息不得揭露內部實作細節 |
| ER-05 | 使用者訊息依 `Accept-Language` 本地化 |
| ER-06 | 每個錯誤碼須於 `CSP-003` 有對應說明與處理建議 |

### 5.1 例外階層

```mermaid
classDiagram
  class DomainError {
    +string code
    +string message
  }
  class ValidationError
  class BusinessRuleError
  class ConcurrencyConflictError
  class IdempotencyConflictError
  class StateTransitionError
  class ResourceNotFoundError
  class ExternalSystemError
  class InfrastructureError
  DomainError <|-- ValidationError
  DomainError <|-- BusinessRuleError
  DomainError <|-- ConcurrencyConflictError
  DomainError <|-- IdempotencyConflictError
  DomainError <|-- StateTransitionError
  DomainError <|-- ResourceNotFoundError
  DomainError <|-- ExternalSystemError
  DomainError <|-- InfrastructureError
```

| 例外 | HTTP | 語意 |
|---|---|---|
| `ValidationError` | 400 | 輸入格式錯誤 |
| `BusinessRuleError` | 422 | 業務規則拒絕 |
| `ConcurrencyConflictError` | 409 | 樂觀鎖衝突 |
| `IdempotencyConflictError` | 409 | 冪等鍵衝突 |
| `StateTransitionError` | 409 | 狀態機不允許之轉換 |
| `ResourceNotFoundError` | 404 | 資源不存在 |
| `ExternalSystemError` | 503 | 外部系統失敗 |
| `InfrastructureError` | 500 | 基礎設施失敗 |

---

## 6. 擴充機制（客製化與自主開發）

對應 `BRD-001` 之客製化需求與 `SYS-5`／`SYS-6`。

| 擴充點 | 機制 | 說明 |
|---|---|---|
| 授權檢核規則 | 實作 `Specification` 並註冊 | 新增檢核項不需改核心 |
| 回饋規則 | 規則表 + 條件表達式 | 多維度組合由參數決定 |
| 手續費／利率 | 計價規則表 | 級距、比例、固定金額 |
| 報表 | 報表定義 + 樣板 | 新增報表不需改碼 |
| 通知樣板 | 樣板表 + 變數替換 | 多語系樣板 |
| 外部介接 | 實作 `Gateway` 埠 | 新增外部系統為新增適配器 |
| 狀態機 | 狀態與轉換表 | 新狀態為資料列 |
| 自訂欄位 | 擴充欄位表（UDF） | 本行可自行新增欄位 |

**規則**：擴充機制**不得**以修改核心程式碼為手段；核心程式碼不得含個別客戶之特例分支。

---

## 7. 設計文件之檢核

| 檢核項 | 標準 |
|---|---|
| 每個服務皆有分層結構 | 100% |
| 每個聚合皆有 ER 定義 | 100% |
| 每個關鍵情境皆有 Sequence | 見 SDD-003 清單 |
| 每個狀態機皆有轉換表 | 見 SDD-005 清單 |
| 每個端點皆有 API 契約 | 100% |
| 無反模式設計 | 0 筆（`GOV-003 §6`） |
| Mermaid 語法 | 0 錯誤 |
