fix: 配置接线审查修复(push数值哨兵化/恒真测试修正/哨兵防漂移/种子映射消双路径)

Important-1: push 数值字段(timeout/max_attempts/retry_backoff_base)
出厂默认改 None 哨兵(与 ai.model 同款),resolve_push_settings 对 None
回退 env——根治 truthy 出厂默认永久遮住 env 覆盖;恒真测试修正(env 数值
patch 成 7.5/5/2.0 与出厂区分)+租户显式数值优先断言;ai.provider 遮
env 的边界记入 docstring。Minor-2: 出厂 model 哨兵与 DEFAULT_CONFIG
一致性测试 + defaults.py 双源注释(model/rate_limit_per_hour)。
Minor-4: allowed_seed_keys → context_seed_map(返回映射,单一取值路径)。
Minor-6/7/3/8: WS 配置冻结时机注释/name_to_region 查表序注释改准确/
chat_rest limit 0 语义注释/resolver None 路径仅供测试注释。404 全绿。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-12 21:57:57 +08:00
parent 32b582aac8
commit 49e2b476f5
7 changed files with 74 additions and 29 deletions
+27 -11
View File
@@ -22,7 +22,7 @@ from app.engine.services import email_service, lead_push_service
from app.engine.services.ai_service import resolve_ai_settings
from app.engine.services.cc_completion import name_to_region
from app.engine.services.conversation import (
ConversationManager, allowed_seed_keys, resolve_contact_flags,
ConversationManager, context_seed_map, resolve_contact_flags,
)
from app.engine.services.rate_limit import _reset_for_test, check
from app.platform.tenant_config import TenantConfig
@@ -106,17 +106,21 @@ def test_send_lead_email_uses_tenant_sender_and_recipients(monkeypatch):
# ---- push ----------------------------------------------------------------
def _patch_push_env(monkeypatch):
"""env PUSH_* 全量 patch——数值刻意取与出厂不同的值(7.5/5/2.0):
出厂哨兵 None 不参与取值,回退是否真实生效由此可判(审查 Important-1,
修复前 env patch 成出厂同值 10/3/1.0 时数值断言恒真)。"""
monkeypatch.setattr(settings, "PUSH_ENABLED", True)
monkeypatch.setattr(settings, "PUSH_API_URL", "env-url")
monkeypatch.setattr(settings, "PUSH_API_KEY", "env-key")
monkeypatch.setattr(settings, "PUSH_EXTERNAL_KEY_PREFIX", "env-pfx")
monkeypatch.setattr(settings, "PUSH_TIMEOUT_SECONDS", 10.0)
monkeypatch.setattr(settings, "PUSH_MAX_ATTEMPTS", 3)
monkeypatch.setattr(settings, "PUSH_RETRY_BACKOFF_BASE", 1.0)
monkeypatch.setattr(settings, "PUSH_TIMEOUT_SECONDS", 7.5)
monkeypatch.setattr(settings, "PUSH_MAX_ATTEMPTS", 5)
monkeypatch.setattr(settings, "PUSH_RETRY_BACKOFF_BASE", 2.0)
def test_push_reads_tenant_section(monkeypatch):
"""PUSH 组全部字段: 租户段给了就用租户的。"""
"""PUSH 组全部字段: 租户段给了就用租户的(显式数值优先于 env——
env 已 patch 成 7.5/5/2.0,断言 5/4/0.5 才证明读的是租户槽)。"""
_patch_push_env(monkeypatch)
r = lead_push_service.resolve_push_settings(_cfg({"push": {
"enabled": True, "url": "https://t.example/push", "api_key": "t-key",
@@ -128,16 +132,19 @@ def test_push_reads_tenant_section(monkeypatch):
"prefix": "t-pfx", "timeout": 5, "max_attempts": 4,
"retry_backoff_base": 0.5,
}
# 租户显式数值优先于 env(哨兵化后 falsy-truthy 争议不再依赖巧合)
assert (r["timeout"], r["max_attempts"], r["retry_backoff_base"]) == (
5, 4, 0.5)
def test_push_empty_section_falls_back_to_env(monkeypatch):
"""空槽(默认 False/空串)视同未设置 → 回退 env PUSH_*。"""
"""空槽(默认 False/空串/数值 None 哨兵)视同未设置 → 回退 env PUSH_*。"""
_patch_push_env(monkeypatch)
r = lead_push_service.resolve_push_settings(_cfg({}).data)
assert r == {
"enabled": True, "url": "env-url", "api_key": "env-key",
"prefix": "env-pfx", "timeout": 10.0, "max_attempts": 3,
"retry_backoff_base": 1.0,
"prefix": "env-pfx", "timeout": 7.5, "max_attempts": 5,
"retry_backoff_base": 2.0,
}
@@ -269,15 +276,24 @@ def test_name_to_region_extras_merged():
def test_chat_rest_seed_keys_from_config():
"""种子键白名单 = config.engine.context_seed_keys 的键集合。"""
"""种子键白名单 = context_seed_map 映射的键集合。"""
cfg = _cfg({"engine": {"context_seed_keys": {
"vehicle_name": "app_vehicle_name", "vehicle_id": "app_vehicle_id"}}})
assert allowed_seed_keys(cfg.data) == {"vehicle_name", "vehicle_id"}
assert set(context_seed_map(cfg.data)) == {"vehicle_name", "vehicle_id"}
# jiancai 出厂 = 旧硬编码白名单的配置化形态
assert allowed_seed_keys(build_jiancai_runtime().config.data) == {
assert set(context_seed_map(build_jiancai_runtime().config.data)) == {
"product_name", "product_id"}
def test_factory_model_sentinel_in_sync():
"""哨兵防漂移(审查 Minor-2): resolve_ai_settings 的"未设置"哨兵必须
与 DEFAULT_CONFIG 出厂 model 一致——默认值一旦漂移,"回退 env AI_MODEL"
永不触发且无测试报错。"""
from app.platform.defaults import DEFAULT_CONFIG
from app.engine.services.ai_service import _FACTORY_DEFAULT_MODEL
assert _FACTORY_DEFAULT_MODEL == DEFAULT_CONFIG["ai"]["model"]
def test_seed_keys_drive_create_conversation(async_db):
"""create_conversation 按映射种子化: 白名单外的 context 键被丢弃。"""