aps-agent/tests/golden/test_gov_api.py

59 lines
3.3 KiB
Python
Raw Permalink Normal View History

2026-07-21 11:05:57 +08:00
# ============================================================
# 治理 API 黄金测试(moduleId: golden-gov-api, 发版门禁 §14.3)
# 固化 M2.5 不变式:
# G1 权力矩阵投影与 _POWER_MAP 一一对应(docs/architecture/harness.md 的机器可验版)
# G2 未登记动作默认 P3(白名单原则)
# G3 黄金测试看板缓存结构合法
# G4 LLM 设置端点不泄露密钥
# ============================================================
from __future__ import annotations # 前向类型引用
from server.agent_core import harness # 门禁(矩阵源)
from server.gateway.golden import golden_status # 看板数据源
# ---------------- G1:policy 投影一致性 ----------------
def test_policy_projection_matches_power_map():
"""list_policy() 的条目集合必须与 _POWER_MAP 完全一致(键与等级)。"""
policy = harness.list_policy() # 投影
assert {p["action"] for p in policy} == set(harness._POWER_MAP), "矩阵键集合不一致" # 键对齐
for p in policy: # 逐条核对
assert p["power"] == harness._POWER_MAP[p["action"]], f"{p['action']} 等级不一致" # 等级对齐
assert p["confirm"] == (p["power"] in ("P2", "P3")), "confirm 标记与等级矛盾" # 确认标记
assert p["desc"], f"{p['action']} 缺中文说明(同步 docs/architecture/harness.md)" # 说明必填
# ---------------- G2:白名单默认拒绝 ----------------
def test_unregistered_action_defaults_to_p3():
"""未登记动作按最严 P3 处理,且必须过确认(guard 直通应抛错)。"""
assert harness.power_of("mcp.dispatch") == "P3" # 未登记 → P3
assert harness.needs_confirm("mcp.dispatch") # P3 必须确认
try:
harness.guard("mcp.dispatch", {}, lambda: None) # 试图直通
raise AssertionError("P3 动作居然直通成功") # 不应到达
except PermissionError: # 预期:硬拒绝
pass
# ---------------- G3:黄金测试看板结构 ----------------
def test_golden_status_shape():
"""看板返回结构必须含齐字段(无缓存时也要返回占位结构)。"""
data = golden_status(run=False) # 只读缓存(不触发跑测防递归)
for key in ("ranAt", "passed", "failed", "total", "cases"): # 必备字段
assert key in data, f"看板缺字段 {key}"
assert isinstance(data["cases"], list) # 用例明细为列表
# ---------------- G4:LLM 设置不泄密 ----------------
def test_llm_settings_no_secret():
"""设置端点返回体中不得出现 api_key 字段值。"""
from server.agent_core.providers import get_provider # 单例
p = get_provider() # 当前配置
payload = { # 端点返回体的等价构造(与 gateway 保持一致)
"provider": p.provider or None, "model": p.model or None,
"baseUrl": p.base_url or None, "enabled": p.enabled,
}
assert "api_key" not in payload and "apiKey" not in payload # 无密钥字段
if p.api_key: # 若配置了密钥
assert p.api_key not in str(payload) # 值不得出现在返回体