From c200d7a52de2cbd68bbdd364642a11610cc978ab Mon Sep 17 00:00:00 2001 From: OG T Date: Thu, 9 Apr 2026 20:11:00 +0800 Subject: [PATCH] =?UTF-8?q?fix(web+k8s):=20CSRF=20mismatch=20+=20NetworkPo?= =?UTF-8?q?licy=20=E7=BC=BA=E5=B0=91=E7=9B=A3=E6=8E=A7=E7=AB=AF=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. pending-approvals-card: 改為點擊時即時 fetch 新 CSRF token 避免多 useCSRF 實例互相覆蓋 cookie 導致 header/cookie 不一致 2. NetworkPolicy: 補開 110:3002(Grafana) 9090(Prometheus) 3001(Gitea) 修正 monitoring probe "All connection attempts failed" Co-Authored-By: Claude Sonnet 4.6 --- .../shared/pending-approvals-card.tsx | 43 +++++++++++++------ k8s/awoooi-prod/02-network-policy.yaml | 12 +++++- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/apps/web/src/components/shared/pending-approvals-card.tsx b/apps/web/src/components/shared/pending-approvals-card.tsx index d8ea3eb4a..dbd795bfd 100644 --- a/apps/web/src/components/shared/pending-approvals-card.tsx +++ b/apps/web/src/components/shared/pending-approvals-card.tsx @@ -10,11 +10,21 @@ import { useState, useEffect } from 'react' import { useTranslations } from 'next-intl' import { useRouter } from 'next/navigation' import { useLocale } from 'next-intl' -import { useCSRF } from '@/hooks/useCSRF' import { CURRENT_USER } from '@/lib/constants/user' const API_BASE = process.env.NEXT_PUBLIC_API_URL ?? '' +// 2026-04-09 Claude Sonnet 4.6: 每次操作前直接 fetch 新 CSRF token +// 避免多個 useCSRF 實例互相覆蓋 cookie,導致 header token 和 cookie 不一致 +async function fetchFreshCsrfHeaders(): Promise> { + try { + const r = await fetch(`${API_BASE}/api/v1/csrf/token`, { method: 'GET', credentials: 'include' }) + if (!r.ok) return {} + const d = await r.json() + return d.token ? { 'X-CSRF-Token': d.token } : {} + } catch { return {} } +} + interface Approval { id: string action: string @@ -35,7 +45,6 @@ export function PendingApprovalsCard() { const t = useTranslations('dashboard') const router = useRouter() const locale = useLocale() - const { getHeaders } = useCSRF() const [approvals, setApprovals] = useState([]) const [actionError, setActionError] = useState(null) const [actioningId, setActioningId] = useState(null) @@ -83,27 +92,33 @@ export function PendingApprovalsCard() {
diff --git a/k8s/awoooi-prod/02-network-policy.yaml b/k8s/awoooi-prod/02-network-policy.yaml index cd0e625ff..df1a8003c 100644 --- a/k8s/awoooi-prod/02-network-policy.yaml +++ b/k8s/awoooi-prod/02-network-policy.yaml @@ -125,10 +125,11 @@ spec: - protocol: TCP port: 11434 - # 允許訪問 192.168.0.110 DevOps 金庫 (Harbor + Sentry + Langfuse + SSH Repair) + # 允許訪問 192.168.0.110 DevOps 金庫 (Harbor + Sentry + Langfuse + SSH Repair + Monitoring) # 2026-03-24 新增: Sentry Self-Hosted # 2026-03-26 新增: Langfuse LLMOps (Phase 15.1) # 2026-04-09 新增: SSH port 22 — repair-bot-110.sh 自動修復 (Bug #11 修正) + # 2026-04-09 新增: Grafana(3002) + Prometheus(9090) + Gitea(3001) — monitoring probe - to: - ipBlock: cidr: 192.168.0.110/32 @@ -146,6 +147,15 @@ spec: # ADR-062: SSH_COMMAND Playbook 需要 K8s Pod → 110:22 的 egress - protocol: TCP port: 22 + # Grafana — monitoring probe + 監控工具卡片 + - protocol: TCP + port: 3002 + # Prometheus — monitoring probe + 監控工具卡片 + - protocol: TCP + port: 9090 + # Gitea — CI/CD 主倉 probe + monitoring + - protocol: TCP + port: 3001 # 允許訪問 192.168.0.112 安全掃描服務 - to: