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:
@@ -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)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
233
docs/adr/ADR-041-periodic-reporting-architecture.md
Normal file
233
docs/adr/ADR-041-periodic-reporting-architecture.md
Normal 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 | 初始提案 |
|
||||
Reference in New Issue
Block a user