Files
Migu2.0/Doc/CODE_REVIEW_ISSUES_2026-05-29.md
zhaowei.huangandCursor 42978930ca feat: 迁入 MiGu.Server、平台前端与车辆列表 reflection 回退
从 Simple-FR 拆出 Platform.Server 并重命名为 MiGu.Server;frontends 源码与构建脚本迁入本仓库。地图监控在 projection/cars 失败或为空时回退 reflection 车辆列表;Simple 仓库已移除旧 Platform.Server。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-29 18:16:34 +08:00

22 KiB
Raw Permalink Blame History

未提交代码审核 — 待优化问题清单

用途:供其他 AI 模型或开发者按项修复。
仓库路径E:\Work\Core\Simple-FR\Simple
分支dev_simpleLite(审核时)
审核日期2026-05-29
审核范围:后端 C#MiGu.Server、SimpleLite、SimpleCore 相关 diff);不含前端 Vue 全量审阅与 dotnet build 验证。


使用说明(给优化 AI

  1. 优先级 从高到低处理:P0P1P2
  2. 每项包含:问题 ID文件现象建议改法验收标准
  3. 修改时遵循仓库现有风格;不要扩大无关重构范围。
  4. 修复后在对应项下可勾选 [x](本文件由人工维护勾选状态)。

问题总表(快速索引)

ID 优先级 状态 标题 主要文件
ISSUE-10 P0 已修复 CarRepository 反序列化白名单可能过严 SimpleLite/Persistence/Repositories/CarRepository.cs
ISSUE-05 P1 已修复 项目/应用配置 API 未校验 writableViaApi SimpleLite/Web/ReflectionApiController.cs
ISSUE-04 P1 🔧 部分处理 Launcher 等新文件未纳入版本库 MiGu.Server/Launcher/*
ISSUE-01 P2 📝 已评估·可配置缓解 登录仍可能阻塞至 Readiness 超时 MiGu.Server/Controllers/AuthController.cs
ISSUE-02 P2 📝 已评估·维持现状 Me/SwitchScope RunMode 复用实例时偏保守 MiGu.Server/Controllers/AuthController.cs
ISSUE-03 P2 已处理·README 默认 admin 凭据(部署) MiGu.Server/appsettings.json
ISSUE-06 P2 已修复 GET monitor-config 写副作用 SimpleLite/Web/ReflectionApiController.cs
ISSUE-07 P2 📝 已评估·待产品 POST monitor-config 立即写盘 SimpleLite/Web/ReflectionApiController.cs
ISSUE-08 P2 已修复 Toolbar GetState 响应格式不一致 SimpleLite/Web/WorkspaceToolbarApiController.cs
ISSUE-09 P2 📝 已评估·技术债 录制/图层 API 重复维护 MapEditApiController + WorkspaceToolbarApiController
ISSUE-11 P2 📝 已评估·观察项 高频 redraw 仍可能偶发旧帧 SimpleLite/Rendering/SimpleSceneRenderer.cs
ISSUE-12 P2 📝 已评估·待产品 Online/Offline 远程 MethodMember 权限 SimpleLite/RCS/CarTypes/Car.cs + 鉴权链
ISSUE-13 P2 📝 已评估·依赖升级 GetPosition realtime 未启用 SimpleLite/Workspace/WorkspacePickSession.cs
ISSUE-14 P2 📝 已评估·环境项 2D 平移绑定依赖 CycleGUI 版本 SimpleLite/Workspace/WorkspaceViewModeService.cs
ISSUE-15 P2 📝 已评估·低优维持 表格双击为时间窗口模拟 SimpleLite/UI/WorkbenchTableRowUi.cs
ISSUE-16 P2 📝 已评估·待产品 底栏 CAD 入口已移除(产品确认) WorkspaceBottomBar.cs

P0 — 合并前建议先验证/修复

ISSUE-10 — CarRepository 反序列化白名单可能过严

  • 状态[x] 已修复(2026-05-29
  • 文件SimpleLite/Persistence/Repositories/CarRepository.csCarTypeBinderJsonOpts
  • 现象TypeNameHandling.Auto + 自定义 ISerializationBinder 白名单未包含 System.StringSystem.Int32System.Boolean 等 BCL 基础类型。customPropsJsonConvert.SerializeObject(car, JsonOpts) 序列化整辆车JSON 中泛型容器(如 Dictionary<string, int>)的 $type 可能含 System.*,反序列化时 BindToTypeSerializationException
  • 风险:升级后 LoadAllIntoSimpleLib 部分车辆加载失败。
  • 建议改法(择一或组合):
    1. 在白名单中增加安全 BCL 类型前缀/精确名:System.StringSystem.Int32System.Int64System.BooleanSystem.SingleSystem.DoubleSystem.DecimalSystem.DateTime 等;或允许 System 下仅 primitive 与 System.Collections.Generic 的封闭列表。
    2. 缩小序列化范围:勿对整个 car 使用 TypeNameHandling.Auto,仅对已知 DTO/字段序列化。
    3. 提供 RegisterAllowedNamespacePrefix("System") 的文档说明(不推荐无限制放行整个 System)。
  • 验收标准
    • 现有生产/测试库中真实 customProps JSON 跑 LoadAllIntoSimpleLib,无 SerializationException。
    • 恶意 $type(如 System.Windows.Forms.* gadget)仍被拒绝。
  • 回归命令(示例):加载含多车型、多插件的程序集后启动 SimpleLite 并打开车辆列表。
  • 修复说明2026-05-29):在 CarTypeBinder 新增精确类型白名单 _allowedExactTypeNames,放行安全的 BCL 基础类型(string/int/long/bool/float/double/decimal/DateTime/DateTimeOffset/TimeSpan/Guid/char/byte/short/Object/Enum/Nullable<T> 等);IsAllowedRawName 在命名空间前缀匹配前先做「精确全名」匹配。修复后泛型容器实参(如 Dictionary<string,int>、Dictionary<string,object>)在字符串层 IsAllowedSerializedTypeName 与已解析层 IsAllowedResolvedType 两条路径均不再误抛 SerializationException。因采用精确全名而非放行整个 System.* 前缀,System.Windows.Forms.* 等 gadget 链仍被拒绝。仍需用真实生产/测试库回归 LoadAllIntoSimpleLib

P1 — 建议本轮一并处理

ISSUE-05 — 项目/应用配置 API 未校验 writableViaApi

  • 状态[x] 已修复(2026-05-29
  • 文件SimpleLite/Web/ReflectionApiController.cs
    • SetProjectFieldPOST /project/fields/{field}
    • SetAppConfigFieldPOST /app-config/fields/{field}
  • 现象:仅检查 FieldMember.lockedMapObjectFactory.IsSensitiveFieldNamePublic检查 FieldMember.writableViaApiSimpleCore/Scene.cs 已新增,默认 true)。
  • 对比MapObjectFactory.TryApplyField 已拒绝 writableViaApi == false
  • 建议改法:在两处 setter 中读取 FieldMember,若 !fm.writableViaApi 返回 403 及明确文案;与 TryApplyField 日志风格一致。
  • 验收标准:对标记 writableViaApi=false 的字段,Web POST 返回 403,内存值不变。
  • 修复说明2026-05-29):在 SetProjectFieldScene.conf)与 SetAppConfigFieldConfiguration.conf)的 fm.locked 检查之后新增 if (!fm.writableViaApi) 拦截,命中即 Diagnosis.Post 记录并返回 403(内存值不变),与 MapObjectFactory.TryApplyField 的双层防御保持一致。注:前端字段列举(ListFieldMembers / 字段记录)暂未暴露 writableViaApi,如需「预先禁用不可写输入框」可后续在响应中增列该布尔值(属前端契约增量,未纳入本次范围)。

ISSUE-04 — 新增文件未纳入 Git(提交遗漏)

  • 状态[~] 部分处理(2026-05-29):.gitignore 已补;编译必需的后端源文件待人工 git add + commit
  • 路径(审核时为 untracked):
    • MiGu.Server/Launcher/SimpleLiteLauncher.cs
    • MiGu.Server/Launcher/SimpleLiteOptions.cs
    • SimpleLite/Web/WorkspaceToolbarApiController.cs
    • SimpleLite/Web/MonitorVisibilityConfig.cs
    • SimpleLite/Workspace/CurveControlPointDragService.cs
    • (前端相关见下方「未审范围」)
  • 现象AuthController 依赖 SimpleLiteLauncher DI;未 add 则他人 clone 无法编译/运行。
  • 建议改法:确认属于本需求后 git add.codegraph/.cursor/mcp.json.gitignore 决定是否提交。
  • 验收标准:干净 clone + build 能通过;Launcher 与 Toolbar 路由可访问。
  • 处理进度2026-05-29):
    • 已补 .gitignore:忽略 .codegraph/(codegraph 本地索引缓存)与 /SimpleCore/ref/(同 /ref/Ref 的未知用途二进制),二者已从 untracked 列表移除。
    • 已确认 AuthController 构造函数注入 SimpleLiteLauncher(第 69/72 行)→ Launcher/*.cs 为编译必需,必须入库。
    • 待人工执行(编译必需的后端源文件 + 本审核文档;单行命令,PowerShell/bash 均可):
git add MiGu.Server/Launcher/SimpleLiteLauncher.cs MiGu.Server/Launcher/SimpleLiteOptions.cs SimpleLite/Web/WorkspaceToolbarApiController.cs SimpleLite/Web/MonitorVisibilityConfig.cs SimpleLite/Workspace/CurveControlPointDragService.cs Doc/ .gitignore
  • 需决策是否入库:.cursor/mcp.json.cursor/rules/codegraph.mdc(团队是否共享该 MCP / 规则配置)。
  • 📦 前端新文件(frontends/apps/simple-platform-vue/**workspaceToolbar.tsMonitorSelectionPanel.vueFieldMemberEditor.vueCarStyleEditor*ProjectPropertiesView.vueMapMonitorConfigView.vue 等)归「前端另开任务」范围,建议随前端审核一并 add。
  • ⚠ 未执行 git commit:提交内容与时机由人工掌控。

P2 — 按产品/环境决定或后续迭代

ISSUE-01 — 登录仍可能阻塞至 Readiness 超时

  • 状态[~] 已评估(2026-05-29):现有配置即可缓解,暂不改代码
  • 文件MiGu.Server/Controllers/AuthController.csLoginTask.Run(() => _launcher.MaybeStart(...))
  • 现象MaybeStartWaitForProjectionReady 默认最多 8000ms,登录请求仍等待该 Task。
  • 建议改法:缩短超时、登录先返回 + 前端轮询 /projection 就绪、或 fire-and-forget + LaunchWarning 已有字段提示。
  • 验收标准:登录 P95 延迟可接受;SimpleLite 未就绪时前端有明确降级(Detached / LaunchWarning)。
  • 评估说明(2026-05-29):报告建议的「缩短超时 / 登录先返回」现有设计已通过配置支持,无需改代码:SimpleLiteOptions.ReadinessTimeoutMs(绑定 appsettings.json:SimpleLite.ReadinessTimeoutMs,默认 8000)注释明确 0 = 不等待(登录立即返回)负值 = 无限等待Login 已用 Task.Run 释放请求线程,失败时回填 Detached + LaunchWarning。运维若需更快登录可将该值调小或置 0(代价:RunMode 可能暂不准,由 LaunchWarning 降级提示)。真正的「fire-and-forget + 前端轮询 /projection」属前后端协议改动,留作后续迭代。

ISSUE-02 — Me / SwitchScope 的 RunMode 在复用外部 SimpleLite 时偏保守

  • 状态[~] 已评估(2026-05-29):当前保守映射为有意设计,维持现状
  • 文件MiGu.Server/Controllers/AuthController.csMeSwitchScopeResolveRunMode
  • 现象ReusingExisting / ExternalReuseLaunchMode 常归为 WebEnabled,与用户本次 WebOnly 选择可能不一致。
  • 建议改法:前端强依赖 LaunchWarning;或 HTTP 探针推断 displayMode(成本高)。
  • 验收标准:用户知悉「已有实例未应用新模式」;无静默错误状态。
  • 评估说明2026-05-29):ResolveRunMode / Me / SwitchScopeExternalReuseLaunchModeReusingExisting 时归 WebEnabled有意的保守降级(代码注释已说明:复用既有实例时其真实 displayMode 不可知,归 WebEnabled 最不会误导用户「以为本地窗口不存在」)。用 HTTP 探针推断成本高且不可靠;前端已可凭 LaunchWarning 提示「已有实例未应用新模式」。结论:维持现状,作为前端体验项后续跟进,不改后端。

ISSUE-03 — 默认 admin 凭据(部署安全)

  • 状态[x] 已处理(2026-05-29):已在 README 增加生产安全须知
  • 文件MiGu.Server/appsettings.jsonAuth:Users
  • 建议:生产用环境变量/密钥管理覆盖;README 注明勿用默认密码。
  • 处理说明2026-05-29):已在 MiGu.Server/README.md 新增「安全须知(生产部署必读)」小节,明确 admin/adminops/opsJwt.Secret/Internal.Token=REPLACE_ME 仅供开发,并给出环境变量覆盖示例(Auth__Users__admin__Password 等)。appsettings.json 默认值保持不变以维持开箱即用的本地开发体验(属部署规范,非代码缺陷)。

ISSUE-06 — GET monitor-config 写副作用

  • 状态[x] 已修复(2026-05-29
  • 文件SimpleLite/Web/ReflectionApiController.csGetMonitorConfig
  • 现象monitorVisibility == null 时 GET 会 Configuration.conf.monitorVisibility = new MonitorVisibilityConfig()
  • 建议改法GET 只读快照,不写回 Configuration.conf;初始化放在 Configuration 构造/FromFile
  • 验收标准:多次 GET 不改变磁盘上的 simple.json(除非 POST)。
  • 修复说明2026-05-29):删除 GetMonitorConfig 中的 Configuration.conf.monitorVisibility = conf; 写回行,GET 改为纯只读快照。monitorVisibility 非 null 已由 Configuration 字段默认值(= new(),第 74 行)、构造函数(??=,第 32 行)与 FromFile??=,第 46 行)三处共同保证,GET 无需补写。多次 GET 不再触碰 Configuration.conf,自然不会引发后续写盘。

ISSUE-07 — POST monitor-config 每次全量写 simple.json

  • 状态[~] 已评估(2026-05-29):维持「保存即写盘」,待产品决定是否需要预览态
  • 文件ReflectionApiController.PostMonitorConfig
  • 现象POST 成功即 Configuration.ToFile("simple.json"),无单独「保存」步骤。
  • 建议改法:若需「预览再保存」,拆分为 PATCH 内存 + POST /monitor-config/save;与 PostAlarmColors / SaveCarStyle 模式对齐。
  • 评估说明2026-05-29):当前「POST 成功即写盘」行为正确(非 bug)。是否拆分为「预览态 + 显式保存」取决于产品对监控可见性配置的交互预期,拆分需新增 POST /monitor-config/save 端点并由前端配合「保存」按钮,属产品/前端联动改动。结论:维持现状,待产品确认是否需要预览态后再迭代。

ISSUE-08 — WorkspaceToolbar GetState 响应格式不一致

  • 状态[x] 已修复(2026-05-29
  • 文件SimpleLite/Web/WorkspaceToolbarApiController.csGetState
  • 现象GetState 返回 { success, code, data };其它端点用 ReflectionEnvelope<object>
  • 建议改法:统一为 ReflectionEnvelope;或前端 adapter 层统一解析(若改 Vue 需另开任务)。
  • 验收标准WorkspaceCanvasToolbar.vue(未审)与 API 契约一致。
  • 修复说明2026-05-29):GetState 成功分支由手写匿名对象 { success, code, data } 改为 ReflectionEnvelope<object>.Ok(BuildStateAnon()),输出补齐 message 字段。经核对前端 workspaceToolbar.tsEnvelope<T> 接口本就声明 { success, code, data, message }unwrap 在失败时读 resp.message——本次改动使后端与该契约完全对齐,dataBuildStateAnon)结构不变,前端仅多读到一个 message 字段,向后兼容,无需改 Vue。

ISSUE-09 — 录制/图层 API 重复

  • 状态[~] 已评估(2026-05-29):逻辑已收敛到共享单例,维持双入口
  • 文件
    • SimpleLite/Web/MapEditApiController.cs/layers/recording/*/playback/*
    • SimpleLite/Web/WorkspaceToolbarApiController.cs(同源能力)
  • 建议改法:抽取 RecordingApiHelper / 单 controller;或文档标明 MapEdit=地图编辑器、Toolbar=Embed iframe,避免双份逻辑漂移。
  • 验收标准:修一处行为两处一致,或 deprecate 其一。
  • 评估说明2026-05-29):核对两个 controller 后确认——MapEditApiController/objects/*/layers/recording/*/playback/*)与 WorkspaceToolbarApiController/toolbar/*都只是薄 HTTP 封装,真正的状态与逻辑均委托给共享单例 PlaybackController / SimulationRecorder / RecordingLibrary / SimpleUI.LayerToShowRef。因此「修一处行为两处一致」本质已满足(无逻辑漂移,仅路由壳与响应组装重复)。分工:MapEdit=地图编辑器全功能页,Toolbar=Embed/CanvasOnly iframe 精简栏。结论:维持双入口(强行合并会牵动两套前端),作为技术债记录;后续若消重可抽取 RecordingApiHelper 收拢响应组装。

ISSUE-11 — 高频 redraw 仍可能偶发旧帧

  • 状态[~] 已评估(2026-05-29):观察项,未复现不改
  • 文件SimpleLite/Rendering/SimpleSceneRenderer.cs
  • 现象:已做 force 16ms、运动 33ms、NotifyStateChanged 直通;极端高频仍可能竞态。
  • 建议:仅在实际复现时合并 redraw 或加锁。
  • 评估说明2026-05-29):现有节流(force 16ms / 运动 33ms / NotifyStateChanged 直通)已覆盖常规场景;极端高频旧帧为理论竞态,未见稳定复现。盲目加锁可能引入渲染线程争用、得不偿失。结论:保持观察,待出现可复现用例再针对性合并 redraw 或加锁。

ISSUE-12 — Car.OnlineCar / OfflineCar 经 Web 反射调用

  • 状态[~] 已评估(2026-05-29):需产品确认角色边界,未擅自加限制
  • 文件SimpleLite/RCS/CarTypes/Car.cs;调用链 ReflectionApiController + Platform 鉴权
  • 建议:确认 Platform 角色是否允许远程触发;必要时 MethodMember 加权限或 Web 层拦截。
  • 评估说明2026-05-29):OnlineCar / OfflineCarReflectionApiController 反射触发,已受 Platform JWT 鉴权链保护(需登录且具备相应 scope)。是否进一步收紧(仅 role-platform、或 MethodMember 增权限位)取决于产品对「远程上/下线车辆」的角色边界定义,属权限策略决策,不宜由代码审核单方收紧(可能误伤合法运营操作)。结论:待产品确认角色边界后再决定是否加 MethodMember 权限或 Web 层拦截。

ISSUE-13 — GetPosition realtime 未启用

  • 状态[~] 已评估(2026-05-29):阻塞于 CycleGUI 协议,维持注释
  • 文件SimpleLite/Workspace/WorkspacePickSession.cs
  • 现象getPos.realtime = true 仍注释;依赖 OnPickFeedback 双路驱动拖动。
  • 建议:CycleGUI 协议支持后取消注释并删「尚未上线」说明。
  • 评估说明2026-05-29):getPos.realtime = true 依赖 CycleGUI 协议层支持,当前版本未提供,强行开启会导致拖动反馈异常;现有 OnPickFeedback 双路驱动已能正常工作。结论:阻塞于外部依赖(CycleGUI 升级),维持注释现状,待协议支持后取消注释。

ISSUE-14 — 2D 平移绑定依赖 CycleGUI API

  • 状态[~] 已评估(2026-05-29):环境/版本项,建议补版本矩阵
  • 文件SimpleLite/Workspace/WorkspaceViewModeService.csTryBind2DPanOnly
  • 现象:反射 SetWorkspaceBehaviour 字段名;版本不匹配时 2D 右键可能仍改俯仰。
  • 建议:版本矩阵文档;失败时 UI 提示升级 CycleGUI。
  • 评估说明2026-05-29):TryBind2DPanOnly 经反射读 SetWorkspaceBehaviour 字段名,与 CycleGUI 版本强相关。本质是「运行环境/依赖版本匹配」问题,非代码逻辑缺陷。结论:作为环境项记录;建议在 CycleGUI 版本矩阵文档标注最低版本,并在反射失败时通过 UI 提示升级(可后续小改)。本轮不改逻辑以免误判版本。

ISSUE-15 — 表格双击为 400ms 时间窗口模拟

  • 状态[~] 已评估(2026-05-29):可接受方案,维持
  • 文件SimpleLite/UI/WorkbenchTableRowUi.cs
  • 说明CycleGUI 无原生 DoubleClick;已有 PruneExpiredClickTimestamps 防泄漏。
  • 评估说明2026-05-29):CycleGUI 立即模式 UI 无原生 DoubleClick 事件,400ms 时间窗口模拟是合理的既定方案,且已有 PruneExpiredClickTimestamps 防时间戳泄漏。结论:方案可接受,维持现状,低优先级。

ISSUE-16 — 底栏 CAD 入口已移除

  • 状态[~] 已评估(2026-05-29):非 bug,待产品确认无强依赖
  • 文件WorkspaceBottomBar.csWorkspaceFloatingToolbar.cs
  • 说明:CAD 仍可通过主菜单/插件;确认用户无强依赖底栏入口。
  • 评估说明2026-05-29):底栏 CAD 入口移除是产品调整(非缺陷),CAD 功能仍可经主菜单/插件访问。结论:非 bug,仅需产品确认用户无对「底栏 CAD 入口」的强依赖即可关闭。

已确认修复项(无需再改,供对照)

说明
脚本 KPI script count 改为 CarProgram.GetPrograms().Length
脚本 CRUD Web 禁止新建/删除 scriptResolveObject 走 CarProgram
删 script 误删车 MapObjectFactory.DeleteByKind script 分支独立返回 400
JSON camelCase SetViewFilter 用 DictionaryToolbar 用 JsonSerializerCase.CamelCase
敏感字段 MapObjectFactory 前缀黑名单 + writableViaApi
项目保存路径 TryResolveSafeProjectPath 白名单
对齐/选择解耦 WorkspacePointerSnapAlignSnap*
GetPosition 竞态 terminated ReferenceEquals 防误删新会话
车体默认白色 WorkspaceViewportStyle 纯白判定修复

未审范围(后续可另开审核任务)

  • frontends/apps/simple-platform-vue/**(含 DashboardView.vue 等大 diff
  • SimpleLite/UI/ComposerDockPanel.cs 大 diff
  • build-platform-frontend.bat
  • 全解决方案 dotnet build / 前端 npm run build
  • 未跟踪前端文件:workspaceToolbar.tsWorkspaceCanvasToolbar.vueCarStyleEditor*.vue

给优化 AI 的推荐执行顺序

1. ISSUE-10(回归真实 DB → 修 binder 或序列化策略)
2. ISSUE-05writableViaApi 对齐)
3. ISSUE-04git add 缺失文件)
4. ISSUE-08 / ISSUE-09(若本轮动前端 Toolbar
5. 其余 P2 按产品排期

修订记录

日期 说明
2026-05-29 初版:基于会话 58 代码审核整理
2026-05-29 优化轮(会话 65):修复 ISSUE-10/05/06/08(代码改动);ISSUE-03 在 MiGu.Server/README.md 增「安全须知」、ISSUE-04 补 .gitignore 并给出 git add 命令(后端必需文件待人工提交);ISSUE-01/02/07/09/11/12/13/14/15/16 完成评估并记录决策。dotnet build SimpleLite/SimpleLite.csproj 通过(0 错误 / 282 预存警告)。