fix(security): 多租户隔离全量修复 security-fix multi-tenant (OpenCode审查P0)
- bot_bridge 18数据端点全部 entity_id 隔离(Depends(get_entity_id)/body),/ping /risk-levels 豁免 - alert_rules 11端点 entity_id 隔离 + KPIAlert/DynamicThresholdCache 写入 entity_id - reports 17端点隔离 + generate_report 写 ReportHistory.entity_id + history 按 entity 过滤 - ai_analysis 移除硬编码默认key,改 _require_deepseek_key() 强制 env 缺失 503 - budget auto-decompose 硬编码 entity_id==1 改请求 entity - kpis update_kpi 加 UPDATE_KPI_WHITELIST 白名单(status/important_flag 不可越权改) - data_quality 收敛:删 MySQL JSON 版 _run_rule_checks,check-governance 复用 _run_governance_checks(SQLite 兼容) - _eval_threshold invert 参数修复(>=↔< 等取反),red 分支不传 invert 保持行为 - 新增 test_security_multitenant.py 13条(bot_bridge/alert_rules/reports 隔离 + invert + SQLite governance) - models 6表加 entity_id 列;生产库已 ALTER + 按真实归属回填(kpi_alerts 472行中216行属entity≠1)
This commit is contained in:
@@ -119,6 +119,7 @@ class DataSourceConfig(Base):
|
||||
"""数据源配置"""
|
||||
__tablename__ = "data_source_config"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
entity_id = Column(Integer, default=1, comment="企业ID (多租户隔离 2026-08-31 安全修复)")
|
||||
name = Column(String(200), nullable=False, comment="数据源名称")
|
||||
source_type = Column(String(20), nullable=False, comment="erp/business/excel")
|
||||
api_endpoint = Column(String(500), nullable=True, comment="API地址")
|
||||
@@ -134,6 +135,7 @@ class KPIAlert(Base):
|
||||
"""预警记录"""
|
||||
__tablename__ = "kpi_alerts"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
entity_id = Column(Integer, default=1, comment="企业ID (多租户隔离 2026-08-31 安全修复)")
|
||||
kpi_id = Column(Integer, ForeignKey("kpi_definitions.id"), nullable=False)
|
||||
kpi_value_id = Column(Integer, ForeignKey("kpi_values.id"), nullable=True)
|
||||
alert_level = Column(String(20), default="yellow", comment="green/yellow/red")
|
||||
@@ -217,6 +219,7 @@ class ActionPlan(Base):
|
||||
"""改善行动计划"""
|
||||
__tablename__ = "action_plans"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
entity_id = Column(Integer, default=1, comment="企业ID (多租户隔离 2026-08-31 安全修复)")
|
||||
alert_id = Column(Integer, ForeignKey("kpi_alerts.id"), nullable=True, comment="关联预警")
|
||||
kpi_id = Column(Integer, ForeignKey("kpi_definitions.id"), nullable=False, comment="关联KPI")
|
||||
objective_id = Column(Integer, ForeignKey("objectives.id"), nullable=True, comment="关联OKR目标")
|
||||
@@ -247,6 +250,7 @@ class OrgNode(Base):
|
||||
"""组织节点: 集团→事业部→区域→部门→班组 5级"""
|
||||
__tablename__ = "org_nodes"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
entity_id = Column(Integer, default=1, comment="企业ID (多租户隔离 2026-08-31 安全修复)")
|
||||
parent_id = Column(Integer, ForeignKey("org_nodes.id"), nullable=True, comment="父节点ID")
|
||||
name = Column(String(100), nullable=False, comment="节点名称")
|
||||
code = Column(String(50), unique=True, nullable=True, comment="编码")
|
||||
@@ -534,6 +538,7 @@ class ReportHistory(Base):
|
||||
"""自动生成的经营分析报告记录"""
|
||||
__tablename__ = "report_history"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
entity_id = Column(Integer, default=1, comment="企业ID (多租户隔离 2026-08-31 安全修复)")
|
||||
report_type = Column(String(20), nullable=False, comment="weekly/monthly/special")
|
||||
period = Column(String(20), nullable=False, comment="期间: 2026-W30 / 2026-07 / 2026-Q2")
|
||||
title = Column(String(200), nullable=False, comment="报告标题")
|
||||
|
||||
Reference in New Issue
Block a user