diff --git a/deploy/profile-scripts/mofin_db.py b/deploy/profile-scripts/mofin_db.py index b3262770..0350e33b 100644 --- a/deploy/profile-scripts/mofin_db.py +++ b/deploy/profile-scripts/mofin_db.py @@ -2131,7 +2131,7 @@ def write_holding_strategy(conn, code: str, name: str, data: dict, data['stop_loss'] = float(_op[2]) data['take_profit'] = float(_op[3]) print(f" [AUTHORITY-POS] {code} 保护系统仓位'{_old_pos_val[:30]}'", flush=True) - elif _old_ra: + elif _old_ra: try: from datetime import datetime as _ddt3, timedelta as _dtd3 _ra_dt3 = _ddt3.fromisoformat(str(_old_ra)[:19]) diff --git a/deploy/profile-scripts/mofin_health.py b/deploy/profile-scripts/mofin_health.py index 6c4fe9cf..1c24e239 100644 --- a/deploy/profile-scripts/mofin_health.py +++ b/deploy/profile-scripts/mofin_health.py @@ -940,6 +940,24 @@ def build_report(): flow_status = "read_only" else: flow_status = "orphan" + wcnt, rcnt = len(writers), len(readers) + # 2026-08-19 多写方风险(老莫:数据篡改风险的根源) + # 写方>=3 → 高风险(多个模块竞争写同一实体,可能互相覆写/篡改) + if wcnt >= 3: + risk = "high" + risk_note = f"⚠️多写方{wcnt}(竞争写,可能篡改)" + elif wcnt == 0: + risk = "orphan" + risk_note = "无写方(死实体)" + elif rcnt == 0: + risk = "write_only" + risk_note = "写无读(幽灵)" + elif wcnt == 2: + risk = "watch" + risk_note = f"{wcnt}写方(需关注)" + else: + risk = "ok" + risk_note = "" entities.append({ "name": tname, "desc": TABLES_DESC.get(tname, ""), @@ -947,11 +965,16 @@ def build_report(): "rows": cnt, "readers": readers[:10], "writers": writers[:10], + "writer_count": wcnt, + "reader_count": rcnt, + "multi_writer": wcnt >= 3, + "risk": risk, + "risk_note": risk_note, "has_input": has_input, "has_output": has_output, "orphan": flow_status in ("orphan", "read_only", "write_only"), "flow_status": flow_status, - "warn": flow_status != "healthy", + "warn": flow_status != "healthy" or wcnt >= 3, "flow_detail": flow_detail, }) diff --git a/static/mofin_health.html b/static/mofin_health.html index 4630f6b7..84923ce8 100644 --- a/static/mofin_health.html +++ b/static/mofin_health.html @@ -269,6 +269,14 @@ function renderDataFlow(entities, jsonFiles, architecture) { } html += `显示 ${filtered.length} 个数据表 + ${jf.length} 个JSON文件的读写流向。绿色→写入,蓝色→读取。`; + // 2026-08-19 多写方风险汇总 + const risky = filtered.filter(e => (e.risk==='high'||(e.writers||[]).length>=3)); + if (risky.length > 0) { + html += `