# SAD-006　部署架構與可觀測性

| 項目 | 內容 |
|---|---|
| 文件編號 | SAD-006 |
| 版本 | 1.3 |
| 狀態 | 已核定 |
| 撰寫者 | SA / SRE |
| 審查者 | TL / SEC |
| 對應需求 | SYS-2.9、SYS-2.10、SYS-2.11、B.1 基礎設施、B.3 雲原生原則、POC-17 |

---

## 1. 雲原生原則落實

| 原則 | 落實方式 |
|---|---|
| 容器化 | 所有服務以容器映像交付，映像不可變 |
| 宣告式組態 | 以 manifest 宣告期望狀態，由編排器收斂 |
| 組態外部化 | 組態由環境變數或組態中心注入，**不打包進映像** |
| 無狀態服務 | 服務不保存本機狀態，狀態存於資料庫或快取 |
| 健康檢查 | 每服務提供 liveness 與 readiness 端點 |
| 優雅關閉 | 收到終止訊號後停止接收新請求並完成進行中請求 |
| 可拋棄 | 任何實例可隨時被替換而不影響服務 |
| 水平擴充 | 以增加實例數擴充，非加大單機 |
| 可觀測 | 內建日誌、指標、追蹤 |
| 自動化 | 建置、測試、部署、回復皆自動化 |

---

## 2. 環境規劃

| 環境 | 用途 | 資料 | 規模 |
|---|---|---|---|
| DEV | 開發自測 | 合成測試資料 | 最小 |
| SIT | 整合測試 | 合成測試資料（含全流程） | 1/4 生產 |
| UAT | 使用者驗收 | 去識別化之生產資料 | 1/2 生產 |
| PERF | 效能測試 | 合成測試資料（生產量級） | 同生產 |
| PROD | 生產 | 真實資料 | 依容量規劃 |

### 2.1 環境隔離

| 面向 | 要求 |
|---|---|
| 網路 | 各環境獨立 VPC／命名空間，禁止跨環境連線 |
| 資料庫 | 各環境獨立實例 |
| 憑證 | 各環境獨立憑證與金鑰 |
| 組態 | 各環境獨立組態，不得共用生產憑證 |
| 外部系統 | 非生產環境一律指向沙箱，**禁止連生產** |

---

## 3. 部署單元與編排

```mermaid
flowchart TD
  subgraph CLUSTER["Kubernetes 叢集（Active-Active 雙叢集）"]
    subgraph NS1["命名空間：edge"]
      IGW["Ingress / API 閘道"]
      BFFP["BFF"]
    end
    subgraph NS2["命名空間：domain"]
      D1["authorization ×N"]
      D2["limit ×N"]
      D3["posting ×N"]
      D4["其他領域服務 ×N"]
    end
    subgraph NS3["命名空間：support"]
      S1["statement / clearing / 批次"]
    end
    subgraph NS4["命名空間：platform"]
      CFG["組態中心"]
      OBS2["可觀測性收集器"]
      SEC2["密鑰管理"]
    end
  end
  subgraph DATA2["資料層"]
    ORA1["Oracle Primary<br/>權威 OLTP：CC_SERVICE 各 schema + CC_PLT"]
    ORA2["Oracle Standby<br/>Data Guard"]
    PGP["PostgreSQL Primary<br/>proj / evt / rpt"]
    PGR["PostgreSQL Replica ×N"]
    RDS["Redis Cluster"]
    KFK2["Kafka Cluster"]
  end
  IGW --> BFFP
  BFFP --> D1
  BFFP --> D2
  D1 --> ORA1
  D1 --> RDS
  D2 --> ORA1
  D3 --> ORA1
  ORA1 --> ORA2
  D1 --> PGP
  D1 --> KFK2
  PGP --> PGR
  S1 --> ORA1
  S1 --> PGR
  OBS2 --> KFK2
```

> **v1.1 變更**：資料層原僅列 PostgreSQL，依客戶指定補入 **Oracle 為權威 OLTP**
> （Primary + Data Guard Standby）；PostgreSQL 轉為承擔 CQRS 讀模型、事件流存檔與報表。
> 詳細分工與 schema 落點見 `SAD-003 §3` 與 `CSP-006 §2.4`。

### 3.1 資源配置（單一服務之 Pod 規格基準）

| 服務類型 | CPU 請求／上限 | 記憶體請求／上限 | 副本數（生產） |
|---|---|---|---|
| 閘道 / BFF | 1 / 2 核 | 1 / 2 GiB | 4 |
| 授權服務 | 2 / 4 核 | 2 / 4 GiB | 6 |
| 額度服務 | 1 / 2 核 | 1 / 2 GiB | 4 |
| 帳務服務 | 2 / 4 核 | 2 / 4 GiB | 4 |
| 繳款服務 | 1 / 2 核 | 1 / 2 GiB | 3 |
| 其他領域服務 | 1 / 2 核 | 1 / 2 GiB | 2 |
| 批次服務 | 2 / 8 核 | 4 / 8 GiB | 1（可水平擴充） |

### 3.2 物件儲存：正式方案與本地替代方案（2026-10-01 補建，`HANDOVER #A-106`）

> **用途**：帳單 PDF（`SCS-011 §10`）／報表輸出（`SCS-017 §5.4`）／爭議舉證附件。
> **正式方案**：**客戶之企業物件儲存**（本專案不自建）。
> **本地替代方案**：**Garage**（S3 相容），見下。

#### 3.2.1 ⚠️ 為何**不是** MinIO（查證後之更正）

本案既有文件（`CR-017 §8.1`、`§3.E W-5`）原載「本地已有 **MinIO**（見鐵則）」。
**經 2026-10-01 查證，此記載不成立，且 MinIO 已不可用**：

| 查證項 | 結果 |
|---|---|
| 官方下載站 `https://dl.min.io/server/minio/release/` | **HTTP 410 Gone** |
| 站方原文 | 「The open-source MinIO Server, MinIO Client (mc) and MinIO KES projects are **archived and no longer maintained**. MinIO does not provide product support, **security updates, or security advisories** for them… These files are no longer served from this site.」 |
| `ops/local/docker-compose.yml` 實測 | **從來就沒有** MinIO service（11 個服務中無） |
| → 判定 | **違反本案硬性要求「不要 EOL 的東西」**（客戶資安審查必擋）→ **不採用** |

> ⚠️ **併更正**：`CR-017 §8.1` 之「MinIO 可落地」與專案鐵則中「物件儲存→MinIO（compose 早已內含）」
> **皆為誤**——compose **從未**內含 MinIO。`SCS-017 §5.4` 已於 2026-09-22 更正過一次，
> 本次補上**選型層**之更正。

#### 3.2.2 選型：Garage

| 項目 | 值 | 依據 |
|---|---|---|
| 映像 | **`dxflrs/garage:v2.4.1`** | Docker Hub 標籤實查：有**語意化版本**標籤（`v2.4.1` 最新）且近期仍更新 |
| 為何不選 SeaweedFS | Docker Hub **僅有 `latest`／`dev`／sha**，**無語意化版本標籤** | 違反「**不鎖 `latest`**」之交付要求 |
| 為何不選 LocalStack | 為 **AWS 模擬器**而非物件儲存本體 | 本案要的是「物件儲存」之替代，非「模擬 AWS」 |
| 為何不選 RustFS | 最新標籤為 **`1.0.1-preview.*`**（尚未 GA） | 銀行案不宜採 preview |
| 授權 | AGPLv3 | 本地開發用；**正式環境為客戶之企業儲存**，不涉及散布 |

#### 3.2.3 本地部署定義（`ops/local/docker-compose.yml`）

| 項目 | 值 |
|---|---|
| Compose profile | **`storage`**（與 `obs`／`iam`／`tools`／`oracle` 並列，**不併入 `obs`**——物件儲存非可觀測性） |
| 容器名 | `cc-garage` |
| **S3 API 埠** | **3900**（本案服務所使用） |
| 管理 API 埠 | 3903（維運查詢；**程式不使用**） |
| RPC 3901／靜態網站 3902 | **刻意不對外映射**（單節點下無外部用途，徒增攻擊面） |
| region | **`cardcore`**（由 `config/garage.toml` 之 `s3_region` **自行決定**，非 AWS 固定值） |
| Bucket | **`cardcore-artifacts`**（由 `GARAGE_DEFAULT_BUCKET` 自動建立） |
| 認證 | 靜態 access key／secret key（`GARAGE_ACCESS_KEY`／`GARAGE_SECRET_KEY`，置於 `ops/local/.env`，**不入版控**） |
| 持久化 | named volume `garage-data` → `/var/lib/garage`（`metadata_dir`／`data_dir` 皆在其下） |
| 自動初始化 | 啟動參數 `--single-node --default-bucket`（Garage **v2.3.0 起**支援） |

> ⚠️ **`--default-bucket` 之靜默陷阱**：`GARAGE_DEFAULT_ACCESS_KEY`／`GARAGE_DEFAULT_SECRET_KEY`／
> `GARAGE_DEFAULT_BUCKET` **三者缺一即不自動建立**，且 **Garage 不報錯**（靜默略過）。
> 故 compose 對前兩者用 `${VAR:?訊息}` **強制必填**（缺則 compose 直接失敗）。

> ⚠️ **Healthcheck 之陷阱（實測踩過）**：Garage 映像**沒有 `/bin/sh`**（精簡映像）→
> **不可用 `CMD-SHELL` 形式**：Docker 會 exec `/bin/sh` 失敗，容器**恆顯示 `unhealthy`**，
> 而服務**完全正常**（實測 `3903/health` → **200**）——這是**健康檢查本身壞掉**
> （false negative），**比沒有 healthcheck 更危險**：會讓
> `depends_on: condition: service_healthy` **永遠不滿足**。
> **正解**：用 **exec 形式** `test: ["CMD", "/garage", "status"]`——它會**實際連 RPC**，
> 是真正的就緒檢查（實測改後 **2 個週期內轉 `healthy`**）。

#### 3.2.4 ⚠️ 契約是 **S3 API**，故**本地後端可換**

本案程式**只依賴 S3 API**（`s3_region` ＋ endpoint ＋ 靜態憑證），
**不依賴任何 Garage 專屬特性**。因此：

- 換本地後端（Garage → 其他 S3 相容）＝ **改 compose ＋ 組態，程式不動**
- 接正式環境（客戶企業物件儲存）＝ **只換 endpoint 與憑證**
- 此即「**埠（port）**」之價值——與 `KeyProvider`／`ServiceClientHttpClient` 同一思路

#### 3.2.5 ⚠️ 未竟（誠實揭露）

1. **接線進度：`report-service` 已接、`statement-service` 尚未**（2026-10-01 更新，`HANDOVER #A-107`）：
   `report-service` 之報表輸出**已改走物件儲存並真機驗證**（`SCS-017 §8.1`）。
   ⚠️ **`statement-service` 之帳單 PDF 仍未接**——因其 **PDF 產生器本身尚未實作**
   （需額外函式庫，`SCS-011 §10`）→ **不是「忘了接」，是「沒有東西可接」**；
   該項另立任務處理。
2. Java SDK **已 spike 驗證**：**AWS SDK v2 for Java `2.55.9`**
   （`:s3` 與 `:bom` 於 Maven Central 實查存在；**編譯 ＋ 執行期皆通過**，見 `§3.2.6`）。
   ⚠️ **併載兩個 S3 相容性地雷**（實測踩到並修除，`SCS-017 §8.1.7`）：
   **①** SDK 2.30 起預設校驗＋`aws-chunked` 會被 S3 相容實作拒絕（**400 `Invalid payload signature`**）；
   **②** 校驗設定**只能在一處**，兩處並設會**啟動期失敗**。
3. 本地為**單節點、無冗餘**（`replication_factor = 1`）——**嚴禁**用於 SIT 以上。
4. `config/garage.toml` 之 `rpc_secret`／`admin_token` 為**本地開發專用**，
   與 `config/keycloak-realm.json` 之 dev secret **同一政策**（本地單機、非生產憑證）；
   SIT／UAT／PROD 一律由密鑰管理提供（`§2.1`）。
5. **下載呈現方式尚未實作**（`SCS-017 §8.1.4`）：`DOWNLOAD_URL` 現存**物件鍵**，
   但「如何下載」（動態 presigned vs 代理端點）**待 BEAM PMO 裁定** → 目前前端只顯示鍵值。

#### 3.2.6 驗證範圍（誠實揭露）

| 已驗證 | 未驗證 |
|---|---|
| 映像 `dxflrs/garage:v2.4.1` **可拉取** | 多節點／冗餘行為（本地刻意單節點） |
| `garage status` → **HEALTHY NODES**、`v2.4.1` | 正式環境之企業物件儲存互通性 |
| **bucket `cardcore-artifacts` 自動建立**、access key 自動建立 | 大檔／分段上傳（multipart）行為 |
| **S3 API PUT／GET 往返**（`HANDOVER #A-106`） | **`statement-service` 之帳單 PDF 接線**（產生器未實作） |
| ✅ **Java SDK（`awssdk:s3:2.55.9`）之編譯與執行期相容**——`report-service` 啟動成功、作業 `COMPLETED`、**物件可自 Garage 取回**（`#A-107`） | **下載呈現方式**（presigned／代理端點）尚未實作 |

---

## 4. 擴縮容

### 4.1 自動擴容（對應 POC-17）

| 觸發條件 | 動作 | 範圍 |
|---|---|---|
| CPU 使用率 > 60% 持續 1 分鐘 | 增加副本 | 最大 3 倍 |
| 記憶體使用率 > 60% 持續 1 分鐘 | 增加副本 | 最大 3 倍 |
| 請求佇列深度 > 門檻 | 增加副本 | 最大 3 倍 |
| CPU 使用率 < 25% 持續 10 分鐘 | 減少副本 | 最小基準副本 |

**驗收要求（POC-17）**

| 情境 | 要求 |
|---|---|
| 平常 | 200 TPS（使用率 20%） |
| 尖峰觸發 | 使用率達 60% 自動擴容，最大達 2,000 TPS |
| 擴容生效時間 | ≤ 3 分鐘 |
| 尖峰期間其他交易 | P99 劣化 ≤ 20% |
| 授權成功率 | 100%（不含正常拒絕） |

### 4.2 限流與削峰

| 層次 | 機制 |
|---|---|
| 閘道 | 依用戶／端點限流（見 `SAD-004 §3.4`） |
| 服務 | 併發上限、佇列上限 |
| 外部呼叫 | 節流控管（依對方容量） |
| 非即時工作 | 佇列削峰，離峰處理 |

---

## 5. 高可用與備援

### 5.1 架構

| 層次 | 設計 |
|---|---|
| 應用 | 多副本跨節點、跨可用區 |
| 資料庫 | Primary + Sync Replica + Async Replica |
| 快取 | Redis Cluster（多主） |
| 訊息 | Kafka 多副本（replication factor ≥ 3） |
| 負載平衡 | 多層（DNS → LB → Ingress → Service） |
| 機房 | Active-Active 雙活 |

### 5.2 目標值

| 指標 | 目標 |
|---|---|
| 系統可用率 | ≥ 99.99% |
| RTO（復原時間目標） | ≤ 30 分鐘 |
| RPO（復原點目標） | ≤ 5 分鐘 |
| 單一節點失效 | 服務不中斷 |
| 單一可用區失效 | 服務不中斷（降容量） |
| 單一機房失效 | 切換至另一機房，RTO ≤ 30 分鐘 |

### 5.3 故障處理

| 故障 | 處理 |
|---|---|
| 服務實例失效 | 編排器自動重建；健康檢查摘除 |
| 資料庫 Primary 失效 | 自動切換至 Sync Replica |
| Kafka 節點失效 | 分區 leader 自動轉移 |
| 快取失效 | 回退直查資料庫（降級） |
| 外部系統失效 | 斷路器 + 降級（如 Stand-in） |
| 發卡主機失效 | Stand-in 代授權（見 `SAD-004 §4.2`） |

### 5.4 消除單點故障（SPOF）

| 檢查項 | 要求 |
|---|---|
| 應用實例 | ≥ 2 副本，且跨節點 |
| 資料庫 | 具備自動切換能力 |
| 訊息 | replication factor ≥ 3 |
| 快取 | 多主或具備故障轉移 |
| 網路 | 雙線路、雙交換器 |
| DNS | 多重解析 |
| 憑證 | 自動輪替，不依賴單一管理員 |

---

## 6. 部署策略（7×24 不中斷）

### 6.1 藍綠部署

```mermaid
flowchart LR
  LB["負載平衡器"] -->|"100% 流量"| BLUE["藍色環境<br/>v1.0"]
  LB -.->|"0% 流量"| GREEN["綠色環境<br/>v1.1"]
  GREEN --> VER["驗證"]
  VER -->|"通過"| SW["切換流量"]
  SW -->|"100% 流量"| GREEN2["綠色環境<br/>v1.1"]
  SW -.->|"0% 流量"| BLUE2["藍色環境<br/>v1.0（待命）"]
  VER -->|"不通過"| RB["維持藍色"]
```

### 6.2 部署能力（對應 POC-12）

| 能力 | 要求 |
|---|---|
| 視覺化介面部署 | 提供部署介面，可檢視版本與狀態 |
| 部分進版 | 可僅更新部分服務 |
| 部分退版 | 可僅回復部分服務 |
| 一鍵進版 | 單一操作完成部署 |
| 一鍵退版 | 單一操作完成回復 |
| 業務連續性 | 腳本執行期間不影響業務訪問 |
| 封閉驗證 | 支援部署前之封閉環境驗證 |
| 回退時間 | ≤ 1 分鐘（分流回退） |

### 6.3 CI/CD 管線

```mermaid
flowchart LR
  A["提交"] --> B["建置"]
  B --> C["靜態分析"]
  C --> D["單元測試"]
  D --> E["映像建置"]
  E --> F["映像掃描"]
  F --> G["部署 DEV"]
  G --> H["整合測試"]
  H --> I["部署 SIT"]
  I --> J["效能與安全測試"]
  J --> K["部署 UAT"]
  K --> L["驗收"]
  L --> M["部署 PROD<br/>藍綠"]
```

**品質閘門**

| 階段 | 閘門 |
|---|---|
| 建置 | 編譯成功 |
| 靜態分析 | 0 Critical／High |
| 單元測試 | 全數通過、覆蓋率達標 |
| 映像掃描 | 0 High 漏洞 |
| 整合測試 | 全數通過 |
| 效能測試 | 達標 |
| 驗收 | 通過 |

**目標值**：自動構建成功率 ≥ 99%、構建時間 ≤ 10 分鐘、Rollback ≤ 5 分鐘、Zero Downtime 部署成功率 ≥ 99.9%。

---

## 7. 可觀測性

### 7.1 三大支柱

```mermaid
flowchart TD
  subgraph SVC2["服務"]
    LOG["結構化日誌"]
    MET["指標 Metrics"]
    TRC["分散式追蹤 Traces"]
  end
  subgraph COL["收集"]
    C1["日誌收集器"]
    C2["指標收集器"]
    C3["追蹤收集器"]
  end
  subgraph STORE["儲存"]
    S1["日誌儲存"]
    S2["時序資料庫"]
    S3["追蹤儲存"]
  end
  subgraph USE["使用"]
    U1["儀表板"]
    U2["告警"]
    U3["問題追查"]
  end
  LOG --> C1 --> S1 --> U1
  MET --> C2 --> S2 --> U2
  TRC --> C3 --> S3 --> U3
  S1 --> U3
  S2 --> U1
```

### 7.2 結構化日誌

| 欄位 | 必填 | 說明 |
|---|---|---|
| `timestamp` | 是 | ISO 8601（UTC，毫秒） |
| `level` | 是 | `debug` / `info` / `warn` / `error` / `fatal` |
| `service` | 是 | 服務名稱 |
| `trace_id` | 是 | 追蹤識別碼 |
| `span_id` | 是 | 區段識別碼 |
| `message` | 是 | 訊息 |
| `actor_id` | 否 | 操作者（**不得為個資**） |
| `resource` | 否 | 資源標的 |
| `duration_ms` | 否 | 耗時 |
| `error_code` | 否 | 錯誤碼 |
| `stack` | 否 | 堆疊（僅非生產或去識別化） |

**日誌規則**
- 一律 JSON 格式（結構化）。
- **個資一律遮罩**（見 `SAD-005 §5.3`）。
- 禁止以字串拼接方式記錄請求內容。
- 錯誤須記錄 `error_code` 與 `trace_id` 以便追查。

### 7.3 指標

| 類別 | 指標 | 目標／告警 |
|---|---|---|
| 業務 | 授權筆數、核准率、拒絕率 | 異常波動告警 |
| 業務 | 授權 P99 延遲 | ≤ 200 ms |
| 業務 | 路由 P99 延遲 | ≤ 5 ms |
| 業務 | 入帳筆數與金額 | 對帳一致 |
| 業務 | 投影延遲（P95） | ≤ 1 秒 |
| 系統 | CPU／記憶體使用率 | > 60% 告警（觸發擴容） |
| 系統 | 請求速率、錯誤率 | 錯誤率 > 1% 告警 |
| 系統 | 連線池使用率 | > 80% 告警 |
| 系統 | 資料庫連線數與慢查詢 | 慢查詢 > 1 秒告警 |
| 訊息 | Kafka 消費者延遲 | > 10,000 告警 |
| 外部 | 外部系統呼叫成功率與延遲 | 失敗率 > 1% 告警 |
| 安全 | 登入失敗次數、權限拒絕次數 | 異常告警 |

### 7.4 分散式追蹤

| 項目 | 設計 |
|---|---|
| 追蹤識別碼 | 由閘道產生，貫穿所有服務與事件 |
| 傳遞方式 | HTTP 標頭 `X-Trace-Id`；事件信封 `traceId` |
| 區段 | 每個外部呼叫、資料庫查詢、事件發布產生一個 span |
| 取樣 | 生產 10% 取樣；錯誤 100% 取樣 |
| 關聯 | 事件之 `causationId` 可回溯至觸發命令 |

**驗收要求（POC-14 步驟 8）**：AP log、Kafka log、Listener log 三者須可依 `trace_id` 串接為完整鏈路。

### 7.5 告警分級

| 級別 | 條件 | 通知 | 回應 |
|---|---|---|---|
| P1 | 服務不可用、授權成功率 < 95% | 電話 + 即時通訊 | 立即 |
| P2 | 效能劣化、錯誤率 > 1% | 即時通訊 | 15 分鐘內 |
| P3 | 單一實例異常、容量告警 | 即時通訊 | 1 小時內 |
| P4 | 趨勢告警 | 郵件 | 當日 |

---

## 8. 容量規劃

| 元件 | 規劃基準 | 擴充方式 |
|---|---|---|
| 授權服務 | 1,000 TPS（未分庫分表）；尖峰 2,000 TPS | 水平擴充副本 |
| 閘道 | 3,000 TPS | 水平擴充 |
| 資料庫 | 1,000 萬客戶、2,000 萬卡號 | 讀寫分離 → 分表 → 分庫 |
| Kafka | 尖峰 5,000 訊息／秒 | 增加分區與 broker |
| 快取 | 熱資料集（額度、參數） | 增加節點 |
| 批次 | 1,000 萬筆交易／小時（POC-16） | 多工參數調整、水平擴充 |

**POC-16 要求**：帳單日批次於 **1 小時內完成**；批次期間 ONLINE 至少維持 **200 TPS**。

---

## 9. 維運手冊（Runbook）要項

| 情境 | 處置 |
|---|---|
| 服務異常 | 確認健康檢查 → 檢視日誌與追蹤 → 必要時重啟或回退 |
| 授權延遲升高 | 檢視資料庫與快取 → 確認擴容 → 必要時限流 |
| 事件延遲 | 檢視 Kafka 消費者延遲 → 擴充消費者 |
| 資料庫切換 | 依 Runbook 執行主從切換 → 驗證一致性 |
| 批次異常 | 定位異常資料 → 排除 → 自 Checkpoint 續跑 |
| 外部系統異常 | 確認斷路器狀態 → 切換備援或降級 |
| 回退 | 執行分流回退（≤ 1 分鐘）或版本回退 |
| 災難復原 | 依 DR 程序切換機房，驗證 RTO／RPO |

---

## 10. 檢核

| 檢核項 | 標準 |
|---|---|
| 所有服務有健康檢查端點 | 100% |
| 所有服務有結構化日誌 | 100% |
| 所有服務有指標輸出 | 100% |
| 追蹤可貫穿服務與事件 | 100%（POC-14 步驟 8） |
| 無單點故障 | SPOF 檢查 0 項 |
| 部署可零停機 | 藍綠／灰度演練通過 |
| 回退可達標 | ≤ 1 分鐘（分流）、≤ 5 分鐘（版本） |
| 自動擴容可達標 | POC-17 通過 |
| 批次效能可達標 | POC-16 通過 |

---

## 11. 修訂記錄

| 版本 | 日期 | 修訂者 | 說明 |
|---|---|---|---|
| **1.3** | 2026-10-01 | WorkBuddy AI | **§3.2 更新：物件儲存程式接線完成（`HANDOVER #A-107`）**——`report-service` 之報表輸出**已改走物件儲存並真機驗證**（`SCS-017 §8.1`）；**Java SDK `awssdk:s3:2.55.9` 由「未驗證」改列「已驗證」**（編譯＋執行期皆通過）。★ **併載兩個 S3 相容性地雷**（實測踩到並修除）：**①** SDK 2.30 起預設校驗＋`aws-chunked` 會被 S3 相容實作拒絕（**400 `Invalid payload signature`**）；**②** 校驗設定**只能在一處**，兩處並設會**啟動期失敗**。⚠️ **併更正**：`statement-service` 之帳單 PDF **仍未接**——因其 **PDF 產生器本身尚未實作**（**不是忘了接，是沒東西可接**） |
| **1.2** | 2026-10-01 | WorkBuddy AI | **新增 §3.2「物件儲存：正式方案與本地替代方案」（`HANDOVER #A-106`）**。★ **選型更正**：既有文件（`CR-017 §8.1`）原載「本地已有 MinIO」——**經查證不成立且已不可用**：MinIO 開源版（Server／mc／KES）**已封存不再維護**，官方下載站 `dl.min.io` 回 **410 Gone**，明載不提供**安全更新**→ **違反硬性要求「不要 EOL 的東西」**。改採 **Garage `v2.4.1`**（Docker Hub 有語意化版本標籤且活躍；SeaweedFS 僅 `latest`、RustFS 為 preview、LocalStack 為 AWS 模擬器，皆不採）。**本地部署**：profile **`storage`**、S3 API 埠 **3900**、region **`cardcore`**、bucket **`cardcore-artifacts`**、憑證置 `ops/local/.env`（**不入版控**）。**已實測**：映像可拉取／`garage status` HEALTHY／bucket 與 key 自動建立／**S3 PUT-GET 往返位元組一致**／**負樣本（錯誤 secret → 403）** |
| 1.0 | 2026-09-17 | SA / SRE | 初版 |
| 1.1 | 2026-09-18 | SA / SRE | §3 部署單元與編排之「資料層」原僅列 PostgreSQL Primary/Replica、Redis、Kafka；依客戶指定「Oracle 為主」補入 **Oracle Primary（權威 OLTP：`CC_*` 各服務 schema + `CC_PLT`）** 與 **Oracle Standby（Data Guard）**，並調整服務至資料層之連線關係。PostgreSQL 轉為承擔 CQRS 讀模型（`proj`）、事件流存檔（`evt`）與報表（`rpt`）。分工依據見 `SAD-003 §3` 與 `CSP-006 §2.4` |
