fix(cma): 隔离扫尾 — kpi_alert_higher_better 拆账套 + tenant/switch 审计收口
ci/woodpecker/push/main Pipeline was canceled
ci/woodpecker/push/main Pipeline was canceled
任务 dama-entity-isolation-sweep-20260923(DAMA 独立回查漏项 / 任总 2026-09-23「按照建议执行」)
① 补漏同源全局键 kpi_alert_higher_better(system_configs,零 DDL)
- deviation_engine: 新增 higher_better_key(entity_id);get_higher_better_codes(db, entity_id)
改为只读本账套键、不回退旧全局键;未配置 → DEFAULT_HIGHER_BETTER(兜底,与原行为逐字一致)
- budget.py: GET/PUT /alert-direction 挂 get_entity_id,只读写会话账套键;body entity_id 不信
- scripts/migrate_higher_better_key_entity_20260923.py: --check/--apply/--down + 库名保护 + 幂等
- 生产实况:库内该键 0 行 ⇒ 无原值可搬运(--apply 走 skip 零写入),e1 行为不变
② kpi_visibility 口径裁定:角色级天然全局 = 非账套维度,不拆(关闭本项)
- auth_middleware 注释 + docstring 登记「有意不做账套后缀」;口径字典
docs/global-config-keys-caliber-20260923.md(含 budget_mode/budget_driver_mode 评估结论)
③ tenant/switch 审计收口
- detail 显式 from_entity_id → to_entity_id + source + operator{id,username,name,role}
- 审计失败不静默:同事务回滚 + AUDIT_WRITE_FAILED ERROR + HTTP 500(不留「改了但没审计」)
- GET /current 无写路径不落审计;历史缺口不补写
证据:新增/改写用例 17 条;全量 1397 passed(去新增文件 1380 + 17);RED 态 8 failed
This commit is contained in:
@@ -32,10 +32,32 @@ DEFAULT_HIGHER_BETTER = [
|
||||
CONFIG_KEY_HIGHER_BETTER = "kpi_alert_higher_better"
|
||||
|
||||
|
||||
def get_higher_better_codes(db, entity_id: int = None) -> list:
|
||||
"""读取越高越好型KPI编码列表(system_configs 可维护,无配置回落默认)"""
|
||||
def higher_better_key(entity_id: int) -> str:
|
||||
"""账套维度的方向配置键名:`kpi_alert_higher_better.<entity_id>`(零 DDL)
|
||||
|
||||
entity_id 必传:`None` → ValueError(防「漏传 → 落默认账套」重演污染)。
|
||||
"""
|
||||
if entity_id is None:
|
||||
raise ValueError(
|
||||
"higher_better_key 必须传 entity_id(账套隔离,2026-09-23 "
|
||||
"dama-entity-isolation-sweep-20260923)"
|
||||
)
|
||||
return f"{CONFIG_KEY_HIGHER_BETTER}.{int(entity_id)}"
|
||||
|
||||
|
||||
def get_higher_better_codes(db, entity_id: int) -> list:
|
||||
"""读取**本账套**越高越好型KPI编码列表(entity_id 必传,漏传 TypeError)
|
||||
|
||||
账套隔离(2026-09-23 dama-entity-isolation-sweep-20260923 §一①,零 DDL):
|
||||
· 只读 `kpi_alert_higher_better.<entity_id>`,**不做「回退旧全局键」**——
|
||||
回退分支本身就是跨账套借用通路(与 `cash.current_balance` 同源缺陷)。
|
||||
· 本账套未配置 → `DEFAULT_HIGHER_BETTER`(业务兜底:方向判定的内置默认表;
|
||||
与拆键前「全局键无行」时的行为逐字一致,故对现存账套零行为差异)。
|
||||
· 旧全局键 `kpi_alert_higher_better` 原样保留作回退杠杆
|
||||
(搬运脚本 `--down` 只删新键,回退老码即可继续读旧键)。
|
||||
"""
|
||||
cfg = db.query(SystemConfig).filter(
|
||||
SystemConfig.config_key == CONFIG_KEY_HIGHER_BETTER
|
||||
SystemConfig.config_key == higher_better_key(entity_id)
|
||||
).first()
|
||||
if cfg and cfg.config_value:
|
||||
try:
|
||||
@@ -43,7 +65,7 @@ def get_higher_better_codes(db, entity_id: int = None) -> list:
|
||||
if isinstance(codes, list):
|
||||
return [str(c) for c in codes]
|
||||
except Exception:
|
||||
logger.warning("system_configs[%s] 解析失败, 回落默认", CONFIG_KEY_HIGHER_BETTER)
|
||||
logger.warning("system_configs[%s] 解析失败, 回落默认", higher_better_key(entity_id))
|
||||
return list(DEFAULT_HIGHER_BETTER)
|
||||
|
||||
|
||||
@@ -301,7 +323,8 @@ def build_deviation_alert(db, kpi, period: str, entity_id: int = 1, min_rate: fl
|
||||
actual = deviation.get("actual_value")
|
||||
budget = deviation.get("budget_value")
|
||||
|
||||
# 方向性:越高越好型(配置化,system_configs.kpi_alert_higher_better)
|
||||
# 方向性:越高越好型(配置化,本账套键 system_configs.kpi_alert_higher_better.<entity_id>;
|
||||
# 2026-09-23 拆账套:entity_id 由调用方必传,不再读全局唯一键)
|
||||
higher_better = kpi.kpi_code in get_higher_better_codes(db, entity_id)
|
||||
|
||||
if higher_better:
|
||||
|
||||
Reference in New Issue
Block a user