fix(web): #17 i18n Hydration 防護 (NEXT_LOCALE Cookie)

Phase D #17: 修復 i18n 語系切換 Hydration 當機

問題: Client/Server 渲染語系落差導致 Hydration Mismatch
解法: Middleware 強制綁定 NEXT_LOCALE Cookie

實作內容:
- 從 URL 路徑提取當前語系
- 強制設定 NEXT_LOCALE cookie (1年 TTL)
- 確保 Server/Client 語系一致

@see QA Report 3.1 節

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
OG T
2026-03-31 11:18:53 +08:00
parent 05cd5ff2a4
commit f25e94e8c4
5 changed files with 362 additions and 3 deletions

View File

@@ -33,6 +33,40 @@
| v2.0 | 2026-03-29 | Claude Code | **🆕 ArgoCD Metrics + TLS 證書監控 (P1/P2 改進)** |
| v2.1 | 2026-03-30 | Claude Code | **🔴🔴🔴 前端內網 IP 禁令 + CD 安全修復** |
| v2.2 | 2026-03-31 | Claude Code | **📊 K3s 優化成效數據 (告警-100%, Pod 重啟-100%, 48h+穩定)** |
| v2.3 | 2026-03-31 | Claude Code | **📅 Phase 21 定期報告機制規劃 (Weekly/Daily E2E/K3s Report)** |
---
## 📅 Phase 21 定期報告機制 (2026-03-31)
> **計畫文檔**: `project_periodic_reporting_plan.md`
> **狀態**: 📋 待統帥批准
### 現有元件復用
| 元件 | 位置 | 復用度 |
|------|------|--------|
| `DailySummaryMessage` | telegram_gateway.py | 100% |
| `RepairReportMessage` | telegram_gateway.py | 100% |
| `StatsService` | stats_service.py | 100% |
| E2E Workflow | .gitea/workflows/e2e-health.yaml | 95% |
### 三階段實施
| Phase | 名稱 | 工時 | 優先級 |
|-------|------|------|--------|
| 21.1 | Daily E2E Schedule | 15 min | P0 |
| 21.2 | K3s Telegram Report | 2h | P1 |
| 21.3 | Weekly Report | 2-4h | P2 |
### 依賴關係
```
Phase 18 (E2E Hardening) ✅
└─► Phase 21.1 (Daily E2E)
└─► Phase 21.2 (K3s Report)
└─► Phase 21.3 (Weekly Report)
```
---

View File

@@ -1,7 +1,60 @@
/**
* Next.js Middleware - i18n + Hydration 防護
* ==========================================
* Phase D #17: 修復 i18n 語系切換 Hydration 當機
*
* 問題: Client/Server 渲染語系落差導致 Hydration Mismatch
* 解法: 強制綁定 NEXT_LOCALE Cookie確保一致性
*
* 版本: v1.1
* 建立: 2026-03-31 (台北時區)
* 建立者: Claude Code
*
* @see QA Report 3.1 節 - i18n 語系切換報錯
*/
import createMiddleware from 'next-intl/middleware'
import { NextResponse, type NextRequest } from 'next/server'
import { routing } from './i18n/routing'
export default createMiddleware(routing)
// 建立 next-intl middleware
const intlMiddleware = createMiddleware(routing)
/**
* 強制綁定 NEXT_LOCALE Cookie
*
* 確保 Server/Client 語系一致,避免 Hydration Mismatch
*/
export default function middleware(request: NextRequest) {
// 先執行 next-intl middleware
const response = intlMiddleware(request)
// 從 URL 路徑提取當前語系
const pathname = request.nextUrl.pathname
const localeFromPath = routing.locales.find(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
)
// 決定最終語系 (優先使用路徑中的語系)
const finalLocale = localeFromPath || routing.defaultLocale
// 🎯 Phase D #17: 強制設定 NEXT_LOCALE cookie
// 確保 Client-side Hydration 時使用相同語系
if (response instanceof NextResponse) {
const existingLocale = request.cookies.get('NEXT_LOCALE')?.value
// 只有當 cookie 不存在或不一致時才設定
if (existingLocale !== finalLocale) {
response.cookies.set('NEXT_LOCALE', finalLocale, {
path: '/',
maxAge: 60 * 60 * 24 * 365, // 1 年
sameSite: 'lax',
})
}
}
return response
}
export const config = {
// 匹配所有路徑,除了以下例外:

File diff suppressed because one or more lines are too long

View File

@@ -5,10 +5,11 @@
---
## 📍 當前狀態 (2026-03-31 01:30 台北)
## 📍 當前狀態 (2026-03-31 02:00 台北)
| 項目 | 狀態 |
|------|------|
| **Phase 21 定期報告** | 📋 **規劃完成,待統帥批准** |
| **#15 SSE + 樂觀更新** | ✅ **完成** (`8c8664c`) |
| **#16 DOM Bypass** | ✅ **完成** (`0b87018`) |
| **Phase A/B/C P1** | ✅ **97/100 OUTSTANDING** |
@@ -65,6 +66,44 @@
---
## 📅 Phase 21 定期報告機制規劃 (2026-03-31 02:00 台北)
### 整合評估結果
| 機制 | 現有復用 | 新增工作 | 工時 | 建議 |
|------|---------|---------|------|------|
| **Daily E2E Schedule** | 95% | +2 行 YAML | 15 min | 🔴 P0 立即 |
| **K3s Telegram Report** | 70% | +Service +Message | 2h | 🟡 P1 本週 |
| **Weekly Report** | 60% | +Template +CronJob | 2-4h | 🟢 P2 下週 |
### 依賴分析
```
Phase 18 (E2E Hardening) ✅
└─► 21.1 Daily E2E Schedule (無依賴)
└─► 21.2 K3s Report (需 Prometheus 數據)
└─► 21.3 Weekly Report (整合 21.1 + 21.2)
```
### 與現有 Phase 關聯
| 關聯 | 類型 | 說明 |
|------|------|------|
| Phase 18 | 延續 | 21.1 是 E2E Hardening 的自動化 |
| ADR-033 | 補強 | 21.2 是 K3s 優化成效的可視化 |
| ADR-037 | 整合 | 21.3 整合 Wave A-D 監控數據 |
### 待統帥決策
1. ✅ Phase 21 編號確認?
2. ✅ Weekly Report 選項 A (Telegram) 或 B (Email)?
3. ✅ Phase 21.1 立即實施?
4. ✅ K3s 報告頻率 (每日/每週)?
**詳細計畫**: `memory/project_periodic_reporting_plan.md`
---
## ✅ 前端 P1 改進完成 (2026-03-31 01:30 台北)
### #16 ThinkingTerminal DOM Bypass

View File

@@ -0,0 +1,233 @@
# ADR-041: 定期報告架構 (Periodic Reporting Architecture)
> **狀態**: 📋 提案 (待統帥批准)
> **日期**: 2026-03-31 (台北時間)
> **決策者**: 統帥 (CEO) + Claude Code (首席架構師)
> **觸發**: K3s 優化成效驗證後,需要定期報告機制
---
## 背景
### 現狀
K3s 優化完成後 (告警 -100%, Pod 重啟 -100%, 48h+ 穩定),缺乏定期報告機制:
| 問題 | 影響 | 根因 |
|------|------|------|
| 無定期健康檢查 | 異常可能延遲發現 | E2E 只在 push 時觸發 |
| K3s 成效無報告 | 統帥無法掌握叢集狀態 | 缺少摘要機制 |
| 週報需人工整理 | 耗費時間,可能遺漏 | 無自動化整合 |
### 現有元件
| 元件 | 位置 | 狀態 |
|------|------|------|
| `DailySummaryMessage` | telegram_gateway.py | ✅ 已實作 |
| `RepairReportMessage` | telegram_gateway.py | ✅ 已實作 |
| `StatsService` | stats_service.py | ✅ 6 方法 + Redis 快取 |
| E2E Workflow | e2e-health.yaml | ✅ 缺 schedule |
| Prometheus | kube-state-metrics | ✅ :30888 |
---
## 決策
### 採用 Phase 21 三階段架構
```
Phase 21: Periodic Reporting
├── 21.1 Daily E2E Schedule (P0 - 15min)
├── 21.2 K3s Status Telegram Report (P1 - 2h)
└── 21.3 Weekly Report Automation (P2 - 2-4h)
```
### 21.1 Daily E2E Schedule
**變更**: `.gitea/workflows/e2e-health.yaml`
```yaml
on:
push:
branches: [main]
workflow_dispatch:
schedule:
- cron: '0 16 * * *' # 每日 00:00 台北 (UTC+8)
```
**觸發機制**: Gitea 內建 schedule
### 21.2 K3s Status Telegram Report
**新增元件**:
```python
# k3s_monitor_service.py
class K3sMonitorService:
async def collect_cluster_status() -> K3sStatusMessage
async def send_daily_report() -> bool
# k3s_status.py
@dataclass
class K3sStatusMessage:
node_total: int
node_ready: int
pod_total: int
pod_running: int
hpa_status: dict
etcd_backup_last: str
velero_backup_last: str
alert_count_48h: int
```
**數據來源**: Prometheus (kube-state-metrics) + kubectl (fallback)
**排程**: K8s CronJob (每日 09:00 台北)
### 21.3 Weekly Report Automation
**選項 A (推薦): Telegram Only**
```python
@dataclass
class WeeklyReportMessage:
week_range: str # "2026-W14"
# 告警統計 (from StatsService)
alert_total: int
alert_critical: int
resolved_rate: float
# AI 效能
ai_proposal_count: int
ai_success_rate: float
# K3s 健康 (from K3sMonitorService)
k3s_uptime: str
hpa_scale_events: int
# Git 活動
commits_count: int
deploy_count: int
# 成本
ai_cost_week: float
```
**排程**: K8s CronJob (每週五 18:00 台北)
---
## 理由
### 為什麼三階段?
| 原則 | 說明 |
|------|------|
| **漸進式** | 由簡到繁,逐步驗證 |
| **復用最大化** | 70%+ 使用現有元件 |
| **風險控制** | 每階段獨立驗證 |
### 為什麼 Telegram 優先?
| 比較 | Telegram | Email |
|------|----------|-------|
| 實時性 | ✅ 即時推送 | ❌ 可能延遲 |
| 互動性 | ✅ 可加按鈕 | ❌ 被動 |
| 實作成本 | ✅ 已有 Gateway | ❌ 需新增 SMTP |
| 歸檔 | ⚠️ 需另存 | ✅ 自然歸檔 |
### 為什麼 CronJob 而非 APScheduler
| 比較 | K8s CronJob | APScheduler |
|------|-------------|-------------|
| 可靠性 | ✅ 叢集管理 | ⚠️ 依賴單 Pod |
| 監控 | ✅ kubectl 可見 | ❌ 需自建 |
| 故障恢復 | ✅ 自動重試 | ❌ 需手動 |
| 符合 ADR-033 | ✅ K3s 原生 | ❌ 應用層 |
---
## 後果
### 優點
- ✅ 自動化健康監控,異常早發現
- ✅ 統帥每日掌握 K3s 狀態
- ✅ 週報自動生成,節省時間
- ✅ 復用現有 70%+ 元件
### 缺點
- ⚠️ 新增 K8s CronJob 需維護
- ⚠️ Telegram 歸檔需另行處理
- ⚠️ 報告格式調整需改代碼
### 風險
| 風險 | 機率 | 緩解 |
|------|------|------|
| Prometheus 不穩定 | 低 | kubectl fallback |
| CronJob 延遲 | 低 | 監控 Job 狀態 |
| Telegram Rate Limit | 低 | 已有去重機制 |
---
## 實施計畫
### 工時預估
| Phase | 工時 | 依賴 |
|-------|------|------|
| 21.1 Daily E2E | 15 min | 無 |
| 21.2 K3s Report | 2h | 21.1 |
| 21.3 Weekly Report | 2h (A) / 4h (B) | 21.1, 21.2 |
| **總計** | **4h 15min** | - |
### 驗收標準
#### 21.1 完成標準
```bash
# Gitea 顯示 scheduled run
curl -s http://192.168.0.110:3001/api/v1/repos/.../actions/runs
# 00:00 台北自動執行
# (查看 Gitea Actions 執行紀錄)
```
#### 21.2 完成標準
```bash
# Telegram 收到 K3s 報告
# (每日 09:00 台北)
# CronJob 狀態
kubectl get cronjob k3s-status-report -n awoooi-prod
```
#### 21.3 完成標準
```bash
# Telegram 收到週報
# (每週五 18:00 台北)
# CronJob 狀態
kubectl get cronjob weekly-report -n awoooi-prod
```
---
## 關聯文件
| 文件 | 用途 |
|------|------|
| `memory/project_periodic_reporting_plan.md` | 詳細計畫 |
| `memory/project_k3s_optimization_metrics.md` | K3s 成效數據 |
| `docs/adr/ADR-033-k3s-ha-architecture.md` | K3s HA 架構 |
| `docs/adr/ADR-037-monitoring-enhancement-architecture.md` | 監控增強 |
| `apps/api/src/services/telegram_gateway.py` | 訊息模板 |
| `apps/api/src/services/stats_service.py` | 統計服務 |
---
## 變更紀錄
| 版本 | 日期 | 執行者 | 變更內容 |
|------|------|--------|----------|
| 1.0 | 2026-03-31 | Claude Code | 初始提案 |