feat(wave6-8): P2.1 fusion + P2.2 governance + P2.4 consensus + Wave 7/8 BLOCKER 修復
承接 Wave 6/7/8 多 engineer 在 agent 限額前完成的代碼,補 commit 解 production HEAD 隱性 import error(decision_fusion 已被 decision_manager 引用但檔案 untracked)。 新增(後端核心): - decision_fusion.py (562 行) — P2.1 方法 III(OpenClaw + Hermes + Elephant 三 LLM 融合) - aiops_timeline.py + aiops_timeline_service.py — critic B4 修復 /api/v1/aiops/timeline endpoint,DB 存取抽到 service 層遵守 leWOOOgo 積木化 - migrations/p2_decision_fusion_columns.sql + rollback — approval_records fusion 欄位 修改(後端整合): - decision_manager.py — fusion 三斷鏈修補(critic B1+B2+B3): · B1: 寫 _evidence_snapshot_ref 到 token.proposal_data · B2: fusion 前計算 complexity_score 並寫 token · B3: fusion composite 寫 token.proposal_data["decision_fusion"] - auto_approve.py — fusion + consensus 認識(critic B3+B5): · composite > 0.7 → auto_execute_eligible bypass min_confidence · source=consensus_engine + score>=0.6 → 規則可信路徑 - consensus_engine.py — db-fix _save_consensus 重用 agent_sessions - governance_agent.py — db-fix _alert PG 寫入 ai_governance_events - approval_db.py — fusion 3 欄位 + 2 partial index + CheckConstraint - db/models.py — schema 對齊 migration - core/config.py — vuln #1 修復:OLLAMA_URL/_FALLBACK_URL field_validator 拒絕公網 IP + 外部域名,僅允許私網/loopback/K8s SVC 白名單 - core/feature_flags.py — P2 fusion + consensus flags - main.py — governance_agent lifespan 啟動 - failover_alerter.py — Wave8-X2: in-memory dedup fallback(Redis 拒絕後不 fail-open) - ollama_*.py — metrics 整合 + recovery 改善 - auto_repair_service.py — verifier 接線 新增(測試 2438 行): - test_decision_fusion.py / test_governance_agent.py / test_consensus_integration.py - test_p2_db_fixes.py / test_wave8_fusion_fixes.py - test_config_url_validation.py(vuln #1 12 tests) - test_failover_alerter.py +Wave8-X2 in-memory dedup 補測 驗收: 116 tests pass (decision_fusion + wave8_fusion + config_url + consensus + governance + p2_db_fixes + failover_alerter) Conflict resolution: - 3 檔(config.py + auto_approve.py + decision_manager.py)git stash pop 衝突 保留 stashed (engineer 最終版),補回 ValueError 「公網 IP」字樣對齊 test Note: 此 commit 解 production HEAD 隱性 import error 仍未修: vuln #4 prompt injection / debugger B14 quota fail-closed / B25-B26 drain_pending_tasks / B8 governance fail alert Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-Authored-By: Multiple Engineers (Wave 6/7/8) <noreply@anthropic.com>
This commit is contained in:
@@ -195,6 +195,64 @@ class Settings(BaseSettings):
|
||||
default="",
|
||||
description="Ollama CPU-only fallback URL (188 備援,P1.1),空字串=停用",
|
||||
)
|
||||
# 2026-04-27 Wave8-X2 by Claude — vuln #1 URL endpoint poisoning 修復
|
||||
# 攻擊情境:攻擊者改 ConfigMap OLLAMA_FALLBACK_URL=http://attacker.com:11434
|
||||
# → ai_router 盲信 → C&C 通道。修法:啟動時拒絕非私網/loopback 的外部 URL。
|
||||
@field_validator("OLLAMA_URL", "OLLAMA_FALLBACK_URL")
|
||||
@classmethod
|
||||
def _validate_ollama_url(cls, v: str) -> str:
|
||||
"""
|
||||
Ollama URL 安全校驗:拒絕非 private/loopback IP 或非已知服務名稱的 URL。
|
||||
|
||||
允許:
|
||||
- 空字串(未設定,OLLAMA_FALLBACK_URL 預設空字串)
|
||||
- 已知 Kubernetes Service hostname 白名單
|
||||
- 私網 IP(RFC 1918)或 loopback(127.x.x.x)
|
||||
|
||||
拒絕:
|
||||
- 公網 IP(8.8.8.8)
|
||||
- 外部域名(attacker.com)
|
||||
"""
|
||||
if not v:
|
||||
return v
|
||||
import ipaddress
|
||||
from urllib.parse import urlparse
|
||||
|
||||
try:
|
||||
host = urlparse(v).hostname or ""
|
||||
except Exception as exc:
|
||||
raise ValueError(f"OLLAMA URL 格式無效:{v!r},錯誤:{exc}") from exc
|
||||
if not host:
|
||||
raise ValueError(f"OLLAMA URL 缺少 hostname:{v!r}")
|
||||
|
||||
# Kubernetes Service hostname 白名單(K8s DNS + 開發別名)
|
||||
_ALLOWED_HOSTNAMES = {
|
||||
"localhost",
|
||||
"ollama",
|
||||
"ollama-svc",
|
||||
"ollama-fallback-svc",
|
||||
"ollama-111",
|
||||
"ollama-188",
|
||||
}
|
||||
if host in _ALLOWED_HOSTNAMES:
|
||||
return v
|
||||
|
||||
# 否則必須是 private/loopback IP
|
||||
try:
|
||||
ip = ipaddress.ip_address(host)
|
||||
except ValueError:
|
||||
# hostname 不是 IP 也不在白名單 → 拒絕
|
||||
raise ValueError(
|
||||
f"OLLAMA URL host 不允許的外部域名:{host!r}(完整 URL:{v!r})"
|
||||
",必須使用私網 IP 或已知 K8s Service hostname"
|
||||
)
|
||||
if not (ip.is_private or ip.is_loopback):
|
||||
raise ValueError(
|
||||
f"OLLAMA URL 必須是私網/loopback IP 或已知 K8s SVC,"
|
||||
f"收到公網 IP {host!r}({v!r}),可能是端點中毒攻擊"
|
||||
)
|
||||
return v
|
||||
|
||||
# 2026-04-25 Claude Engineer-C (P1.1): Ollama 健康檢測推理測試模型
|
||||
OLLAMA_HEALTH_CHECK_MODEL: str = Field(
|
||||
default="qwen2.5:7b-instruct",
|
||||
|
||||
Reference in New Issue
Block a user