fix(security): retire check-governance + scope /reports/dupont to session entity

- data_quality.py: remove GET /check-governance (no caller repo-wide; its
  entity_id param had no session auth -> cross-tenant read; duplicate of
  governance-check) -> the path now returns 404
- reports.py: /reports/dupont resolves the analysis target from the session
  account (assert_entity_slug_scope / resolve_session_slug); explicit
  cross-entity entity param -> 403, illegal value -> 400; the 2026-08-31
  cross-entity exemption is revoked (docstring updated)
- frontend: drop the checkGovernance api definition; DupontAnalysis.vue
  entity radio group -> read-only session entity tag, request without param
- tests: TestCheckGovernanceRetired (404 x2), TestDupontSessionScope (3),
  TestDupont reworked to account-bound tokens (8 tests)
- docs/api-verification-split.md: drop the retired row, note 334/404 -> 333/403

pytest: 10 failed / 957 passed / 1 xfailed vs HEAD baseline 10 failed /
951 passed / 1 xfailed (identical failure set -> zero regression)

(cma-residual-cross-entity-cleanup-20260914)
This commit is contained in:
Hermes CI Fix
2026-09-14 12:09:04 +08:00
parent 72c1bbce16
commit aac1bd1df1
7 changed files with 147 additions and 102 deletions
+5 -40
View File
@@ -342,48 +342,13 @@ RULES_META = {
DETAIL_LIMIT = 10 # 每条规则detail最多列出的条数(避免响应过大)
@router.get("/check-governance")
def check_governance(
entity_id: Optional[int] = Query(0, description="实体ID: 0=全部, 1=酣客, 2=博海"),
db: Session = Depends(get_db),
):
"""DAMA数据治理规则检查(财务七规则)— 返回质量评分+异常清单。
评分规则: 满分100,error级规则每条扣10分,warning级规则每条扣5分,
每条规则最多扣一次分(按规则是否命中,不按count累扣),最低0分。
收敛说明(2026-08-31 安全修复 P1-2):规则执行统一复用
_run_governance_checks(Python 解析 suggestion JSON,SQLite 兼容),
删除原 _run_rule_checks(MySQL JSON_EXTRACT/JSON_VALID 版,SQLite 不兼容)。
本端点保留原评分口径与响应结构(governance-check 端点使用新的扣分口径)。
"""
gov = _run_governance_checks(db, entity_id or 0)
issues = gov["issues"]
# 计算评分(check-governance 原口径:error 扣10 / warning 扣5,每规则最多扣一次)
score = 100
for item in issues:
if item["count"] > 0:
score -= 10 if item["level"] == "error" else 5
score = max(0, score)
passed = [item["rule"] for item in issues if item["count"] == 0]
return {
"checked_at": datetime.now().isoformat(timespec="seconds"),
"entity_id": entity_id or 0,
"score": score,
"total_rules": len(issues),
"issues": issues,
"passed": passed,
"rules_meta": RULES_META,
}
# ============================================================
# 财务七规则检查(governance-check)— 2026-08-30 P1 最终方案
# 与 /check-governance 的区别:
# * 评分规则不同:error 扣 min(15, count*3),warning 扣 min(10, count*1)
# 端点收敛(cma-residual-cross-entity-cleanup-20260914):
# /check-governance 已下线 —— 全仓无调用方(前端仅残留 api 定义、无 .vue 调用);
# 其 entity_id 参数无会话鉴权(0=全部/1/2 任取)→ 跨租户;与 governance-check 功能重复。
# 本端点评分口径:
# * 评分规则:error 扣 min(15, count*3),warning 扣 min(10, count*1)
# * 规则2/3 用 Python 解析 suggestion JSON(不依赖 MySQL JSON 函数)
# * 规则4 区分 error(test/sync/虚拟) 与 manual(待人工确认 warning)
# * 规则7 按 status='active' 口径(与 budget.py 一致,避免多版本叠加失真)