# SAD-001　系統架構總覽

| 項目 | 內容 |
|---|---|
| 文件編號 | SAD-001 |
| 版本 | 1.0 |
| 狀態 | 已核定 |
| 撰寫者 | SA |
| 審查者 | PM / SEC / TL |
| 對應需求 | 全案；SYS-2.6、SYS-7、SYS-8、B.3 微服務與雲原生 |

---

## 1. 架構目標與原則

### 1.1 架構目標

| # | 目標 | 對應業務痛點 | 量測方式 |
|---|---|---|---|
| G1 | 產品規則參數化，新產品不需改碼 | P1 | 新產品上線僅需參數設定 |
| G2 | 支援多層次帳戶結構 | P2 | 歸戶／卡人／卡／子帳四層可運作 |
| G3 | 餘額與額度即時更新 | P3 | 繳款後額度恢復 ≤ 1 秒 |
| G4 | 重複入帳與錯帳可系統性防範 | P4 | 冪等鍵攔阻率 100% |
| G5 | 支援新舊系統並存與分批上線 | P5 | 分流熱更新 ≤ 1 分鐘、回退 ≤ 1 分鐘 |
| G6 | 讀寫分離，尖峰不互斥 | P6 | 授權 P99 ≤ 200 ms、≥ 1,000 TPS |

### 1.2 架構原則（Architecture Principles）

| 編號 | 原則 | 說明 | 違反後果 |
|---|---|---|---|
| AP-01 | **契約優先（Contract-First）** | API 以 OpenAPI 3.1 先定義後實作；契約為跨服務唯一介面 | 服務耦合、無法獨立部署 |
| AP-02 | **資料私有（Database per Service）** | 每個服務擁有自己的 schema，**不得跨庫直接查詢他服務資料表** | 無法獨立演進 |
| AP-03 | **領域純淨（Pure Domain）** | 業務規則置於 `domain/`，不依賴框架、資料庫與網路 | 規則無法單元測試 |
| AP-04 | **參數驅動（Configuration over Code）** | 可變之業務規則一律外部化為參數或規則表 | 違反 `GOV-003 §6.1` |
| AP-05 | **事件驅動（Event-Driven）** | 跨服務之狀態傳播以事件為之，非同步解耦 | 服務間時序耦合 |
| AP-06 | **冪等優先（Idempotent by Design）** | 所有寫入操作須可重複執行而不產生副作用 | 重複入帳 |
| AP-07 | **失敗可見（Fail Loud）** | 錯誤不得靜默；例外須記錄、告警或補償 | 違反 `GOV-003 §6.1` |
| AP-08 | **向後相容（Backward Compatible）** | 契約只增不減；破壞性變更須升版並雙軌 | 上線中斷 |
| AP-09 | **可觀測（Observable）** | 每個請求具備追蹤識別碼，貫穿服務與事件 | 問題無法定位 |
| AP-10 | **安全內建（Secure by Default）** | 預設拒絕、最小權限、個資遮罩 | 資安風險 |

---

## 2. 系統上下文（Context View）

```mermaid
flowchart LR
  HOLDER["持卡人"]
  MERCHANT["特店與收單機構"]
  ORG["卡組織<br/>VISA / MasterCard / NCCC / JCB / AE"]
  TICKET["票證公司<br/>悠遊卡 / 一卡通 / 愛金卡"]

  subgraph SYS["信用卡核心系統（本專案）"]
    GW["API 閘道"]
    SVC["17 個微服務"]
    GW --> SVC
  end

  CREDIT["徵信與徵審系統"]
  CORE["銀行核心系統<br/>CIF / 存款"]
  GL["總帳系統"]
  HSM["HSM 加密機"]
  NOTIFY["通知通道<br/>簡訊 / 電郵 / 推播 / LINE"]
  CHANNEL["數位通路<br/>行動銀行 / 網銀 / 客服系統"]

  HOLDER --> CHANNEL
  CHANNEL --> GW
  MERCHANT --> SVC
  ORG --> SVC
  TICKET --> SVC
  SVC --> CREDIT
  SVC --> CORE
  SVC --> GL
  SVC --> HSM
  SVC --> NOTIFY
```

| 外部系統 | 互動方向 | 介面形式 | 主要用途 |
|---|---|---|---|
| 徵信與徵審系統 | 本系統 → 外部 | REST / 批次 | 進件、評分、核決結果 |
| 銀行核心系統（CIF／存款） | 雙向 | REST | 客戶主檔、存款帳號、自扣 |
| 總帳系統 | 本系統 → 外部 | 檔案 / API | 會計分錄 |
| HSM | 雙向 | 專用協定 | 金鑰、PIN、CVV 驗證 |
| 卡組織 | 雙向 | ISO 8583 | 授權、清算 |
| 票證公司 | 雙向 | 專用協定 | 加值、餘額轉置 |
| 通知通道 | 本系統 → 外部 | REST / 檔案 | 簡訊、電郵、推播、LINE |
| 數位通路 | 雙向 | REST | 客戶端操作與查詢 |

---

## 3. 容器視圖（Container View）

```mermaid
flowchart TD
  subgraph CLIENT["前端"]
    WEB["營運管理平台<br/>React 18 + Vite"]
  end
  subgraph EDGE["邊緣層"]
    GW["API 閘道<br/>路由 / 認證 / 限流"]
    BFF["BFF<br/>前端專用聚合"]
  end
  subgraph DOMAIN["領域服務層"]
    AUTH["authorization-service"]
    LIM["limit-service"]
    CARD["card-service"]
    PTY["party-service"]
    PRD["product-service"]
    POST["posting-service"]
    PAY["payment-service"]
  end
  subgraph SUPPORT["支撐服務層"]
    STM["statement-service"]
    PRC["pricing-service"]
    INS["installment-service"]
    RWD["rewards-service"]
    CLR["clearing-service"]
    DSP["dispute-service"]
    MRC["merchant-service"]
    NOT["notification-service"]
    RPT["report-service"]
    MIG["migration-service"]
  end
  subgraph INFRA["基礎設施"]
    BUS["事件匯流<br/>Kafka"]
    WDB["寫入資料庫<br/>PostgreSQL"]
    RDB["讀取資料庫<br/>PostgreSQL"]
    CACHE["快取<br/>Redis"]
    OBS["可觀測性<br/>日誌 / 指標 / 追蹤"]
  end
  WEB --> GW
  GW --> BFF
  BFF --> AUTH
  BFF --> LIM
  BFF --> CARD
  BFF --> PTY
  BFF --> PRD
  BFF --> POST
  BFF --> PAY
  BFF --> STM
  BFF --> PRC
  BFF --> INS
  BFF --> RWD
  BFF --> CLR
  BFF --> DSP
  BFF --> MRC
  BFF --> NOT
  BFF --> RPT
  BFF --> MIG
  DOMAIN --> BUS
  SUPPORT --> BUS
  DOMAIN --> WDB
  DOMAIN --> RDB
  DOMAIN --> CACHE
  SUPPORT --> WDB
  BUS --> OBS
```

### 3.1 容器職責

| 容器 | 職責 | 不負責 |
|---|---|---|
| API 閘道 | 路由、認證、授權初篩、速率限制、請求追蹤注入 | 業務邏輯 |
| BFF | 前端專用之資料聚合與裁切、避免前端多次往返 | 業務規則 |
| 領域服務 | 領域規則、狀態機、交易邊界 | 前端格式 |
| 支撐服務 | 週期性與批次性業務（帳單、清算、報表） | 即時授權 |
| 事件匯流 | 跨服務狀態傳播、非同步解耦、順序保證（分區內） | 同步查詢 |
| 寫入資料庫 | 權威資料（Single Source of Truth） | 大量查詢 |
| 讀取資料庫 | 查詢最佳化視圖、報表查詢 | 寫入 |
| 快取 | 授權熱路徑之參數與額度快照 | 權威資料 |

---

## 4. 分層架構（每個微服務內部）

採**六角形架構（Ports & Adapters）**，依賴方向一律向內：

```mermaid
flowchart TD
  subgraph OUT["外部"]
    HTTP["HTTP 請求"]
    EVT["事件"]
    DB["資料庫"]
    EXT["外部系統"]
  end
  subgraph IFACE["interfaces（介面層）"]
    CTRL["REST Controller"]
    CONS["Event Consumer"]
  end
  subgraph APP["application（應用層）"]
    UC["Use Case / 服務編排"]
    TX["交易邊界"]
  end
  subgraph DOM["domain（領域層）"]
    ENT["Entity / Aggregate"]
    VO["Value Object"]
    RULE["業務規則"]
    EV["Domain Event"]
  end
  subgraph INFRA2["infrastructure（基礎層）"]
    REPO["Repository 實作"]
    PUB["Event Publisher"]
    ADP["外部系統適配器"]
    OBX["Outbox"]
  end
  HTTP --> CTRL
  EVT --> CONS
  CTRL --> UC
  CONS --> UC
  UC --> ENT
  UC --> RULE
  UC --> REPO
  UC --> PUB
  REPO --> DB
  ADP --> EXT
  PUB --> OBX
```

### 4.1 依賴規則（強制）

| 規則 | 說明 | 自動化檢查 |
|---|---|---|
| DR-01 | `domain/` **不得** import `application/`、`interfaces/`、`infrastructure/` | 依賴掃描 |
| DR-02 | `domain/` **不得** import 任何框架、ORM、HTTP、日誌套件 | 依賴掃描 |
| DR-03 | `application/` 只能 import `domain/` 與其自身之埠（port）介面 | 依賴掃描 |
| DR-04 | `infrastructure/` 實作 `application/` 定義之埠 | 依賴掃描 |
| DR-05 | 服務之間**不得**直接 import 彼此的程式碼 | 依賴掃描 |
| DR-06 | 服務之間**不得**跨庫查詢 | schema 權限檢查 |

> 違反 DR-01～DR-05 由 `CSP-002 §5` 之依賴掃描於 CI 阻擋。

---

## 5. 關鍵架構決策（ADR 摘要）

| 編號 | 決策 | 選項 | 採用 | 理由 |
|---|---|---|---|---|
| ADR-01 | 服務切分方式 | 分層切分／領域切分 | **領域切分（DDD）** | 對齊業務能力，降低跨服務交易 |
| ADR-02 | 跨服務一致性 | 分散式交易／Saga／事件最終一致 | **Saga + 事件最終一致** | 避免分散式鎖；授權為即時、帳務可補償 |
| ADR-03 | 讀寫分離 | 單庫／讀寫分離／CQRS | **CQRS（寫主讀從）** | 滿足 POC-14 之 1 秒同步與尖峰查詢 |
| ADR-04 | 事件傳遞 | 同步呼叫／訊息佇列／事件流 | **事件流（Kafka）** | 順序保證、可重播、解耦 |
| ADR-05 | 授權熱路徑 | 直查資料庫／快取 | **快取 + 資料庫雙寫** | 滿足 P99 ≤ 200 ms |
| ADR-06 | 參數化規則 | 資料庫參數表／規則引擎 | **規則表 + 規則引擎** | 支援多維度組合與版本化 |
| ADR-07 | 冪等實作 | 資料庫唯一鍵／分散式鎖 | **唯一鍵 + 請求指紋** | 無需額外元件，交易內保證 |
| ADR-08 | 金額型別 | 浮點／定點小數／整數最小單位 | **整數最小單位（分）** | 避免浮點誤差（C-01） |
| ADR-09 | 新舊系統並存 | 停機切換／雙軌並行／分流 | **分流（Cycle Split）** | 滿足 P5、POC-13 |
| ADR-10 | 技術棧 | 見 §7 | 見 §7 | 依業主裁定 |

---

## 6. 品質屬性與架構戰術

| 品質屬性 | 目標 | 架構戰術 |
|---|---|---|
| 效能 | 授權 P99 ≤ 200 ms | 熱路徑快取、參數預載、非同步寫入、連線池 |
| 吞吐 | ≥ 1,000 TPS | 水平擴充、分區、無狀態服務 |
| 可用度 | ≥ 99.99% | 多副本、健康檢查、斷路器、降級、Stand-in |
| 一致性 | 授權帳務一致率 ≥ 99.99% | 事件溯源、Outbox、對帳補償 |
| 可修改性 | 新產品不改碼 | 參數化、規則引擎、契約優先 |
| 可測試性 | 領域層覆蓋率 ≥ 90% | 領域純淨、埠／轉接器、依賴注入 |
| 可觀測性 | 全鏈路追蹤 | 追蹤識別碼貫穿、結構化日誌、指標 |
| 安全性 | 個資不外洩 | 加密、遮罩、最小權限、稽核軌跡 |
| 可運維性 | 回退 ≤ 1 分鐘 | 分流熱更新、藍綠部署、Runbook |

---

## 7. 技術棧與埠／轉接器對照

### 7.1 技術棧（參考實作棧）

| 層 | 選型 | 版本 |
|---|---|---|
| 語言 | TypeScript | 5.x（strict） |
| 執行環境 | Node.js | 22 LTS |
| HTTP 框架 | Fastify | 4.x |
| 契約 | OpenAPI | 3.1 |
| 資料庫 | PostgreSQL | 16 |
| 事件 | Kafka | 3.x |
| 快取 | Redis | 7.x |
| 前端 | React + Vite | 18 / 5.x |
| 測試 | Vitest | 2.x |
| 容器 | Docker + Compose（本機）／K8s（生產） | — |

**選型理由**：① 可於本環境立即建置與測試（本機無 Java／Maven／Docker daemon）；
② 與雲原生、容器化部署一致；③ 契約（OpenAPI）與事件（JSON Schema）皆語言中立。

### 7.2 埠／轉接器對照表（若業主指定 Java 21 + Spring Boot 3）

本架構之**領域層與契約層不受技術棧影響**。切換技術棧時僅需替換基礎層轉接器：

| 埠（Port，不變） | TypeScript 轉接器 | Java 轉接器 |
|---|---|---|
| `Repository<T>` | Prisma / pg | Spring Data JPA |
| `EventPublisher` | KafkaJS | Spring Kafka |
| `CacheStore` | ioredis | Spring Data Redis |
| `HttpServer` | Fastify | Spring Web MVC |
| `HsmClient` | 自建適配器 | 自建適配器 |
| `OrgGateway`（卡組織） | 自建適配器（ISO 8583） | 自建適配器（jPOS） |
| `Clock` | 系統時鐘 | `java.time.Clock` |
| `IdGenerator` | ULID | ULID |

> **決策點**：實際開發環境由業主於程式撰寫階段指定（`GOV-003 §4` 條件 8）。
> 無論選用何者，`SDD-000~007` 之設計與 `SDD-006` 之 API 契約**均不需變更**。

---

## 8. 架構檢核

| 檢核項 | 標準 | 對應 |
|---|---|---|
| 服務數與邊界 | 17 個服務，一服務一 bounded context | SAD-002 |
| 依賴規則 | DR-01~DR-06 全數可由 CI 驗證 | CSP-002 §5 |
| 契約覆蓋 | 所有對外 API 皆有 OpenAPI 契約 | SDD-006 |
| 事件覆蓋 | 所有跨服務狀態傳播皆有事件定義 | SAD-004 §5 |
| 個資處理 | 所有個資欄位皆有加密或遮罩設計 | SAD-005 §5 |
| 可觀測性 | 所有服務具備追蹤、日誌、指標 | SAD-006 §5 |
| 無反模式 | 架構文件中無 mock／stub 設計 | GOV-003 §6 |
