Files
lingniu-vehicle-ingest/vehicle-data-platform/docs/oneos-integration-analysis.md

18 KiB
Raw Blame History

OneOS 车辆业务与车辆数据中台集成分析

完整系统、模块、接口、安全、数据库和运维分析见 docs/oneos-ln-asset-management-system-analysis.md。本文件聚焦车辆数据中台集成边界。

更新时间2026-07-14

生产数据库聚合审计结果见 oneos-production-audit-report.md。 涉及 OneOS 的精确修改文件、批次、测试和回滚边界见 oneos-change-approval-proposal.md;该提案尚未执行。 车辆数据中台全部 API 的客户 Scope、IDOR、导出和地图服务覆盖矩阵见 customer-scope-api-enforcement-matrix.md

1. 分析范围与约束

  • OneOS 根目录:/Users/lingniu/project/ai-coding/oneos
  • 核心业务服务:ln-asset-management,分支 dev
  • 相关身份服务:ln-cloud/ruoyi-authln-cloud/ruoyi-system
  • 本轮仅进行只读分析,没有修改 OneOS 文件、数据库或运行配置。
  • 车辆锁车、控车不在本方案范围内。

2. 系统职责边界

详细业务影响与遥测迁移边界见 oneos-business-impact-matrix.md

OneOS 应作为权威来源

  • 客户档案:customer_info
  • 客户账号及启停:ry-cloud.sys_user
  • 车辆基础信息:vehicle_infovehicle_modelvehicle_status
  • 合同客户:vehicle_lease_contract_info
  • 当前车辆交付/归还状态:vehicle_lease_order_record,必要时结合交还车任务表复核
  • 业务筛选维度:运营状态、车型、品牌、运营公司、业务部门、合同和项目

车辆数据中台应作为权威来源

  • 多协议接入状态及最后上报时间
  • 实时位置、车速、SOC 和车辆告警
  • 历史轨迹和原始数据证据
  • 按 VIN 归并后的每日里程、统计期里程和最新总里程
  • 协议数据质量与异常诊断

OneOS 当前仍通过 HASP/旧车联网接口拉取位置和总里程,其中 /vehicle-info/page?withTotalMileage=true 会按 VIN 逐车调用外部 HTTP 接口,存在 N+1 请求。新集成不应让车辆中台反向依赖这条旧链路。

3. 已确认的数据关系

权威表与用途

数据域 主键/关联 集成用途 注意事项
客户档案 customer_info id 客户名称、编码、合作状态 含联系人、银行等敏感字段,范围接口只取最小必要字段
客户账号 ry-cloud.sys_user user_id = customer_info.id 登录、启停、用户类型 账号可能缺失;当前 user_type=customer 未被权限枚举支持
账号角色 ry-cloud.sys_user_rolesys_role user_idrole_id 客户门户功能权限 新客户当前不自动分配角色
车辆档案 vehicle_info idvin VIN、车牌、车型、运营组织 实体已不再保存客户归属VIN 必须核验空值和重复值
车辆状态 vehicle_status vehicle_id 运营、车辆、证照、保险状态 online_status、里程仍混有旧链路数据,不作为中台遥测权威值
合同 vehicle_lease_contract_info idorder_id 主客户、丙方客户、合同和项目 有效客户为 COALESCE(other_customer_id, customer_id)
当前租赁聚合 vehicle_lease_order_record 设计上一车一行 当前客户、合同、最近交还车事实 Mapper 不完整、写入有清空风险,必须审计后使用
租赁历史 vehicle_lease_order_record_log contract_id + vehicle_id 归属和交还车复核 是可追溯证据之一,但当前按组合更新,并非不可变事件日志
交车事实 delivery_vehicle vehicle_idorder_detail_id 核验交车时间、里程和单据 完成状态枚举需与生产字典确认
还车事实 return_vehicle_task vehicle_idcontract_id 核验还车时间、里程和完成状态 多条完成路径会更新聚合表,部分异常不中断主流程

车辆数据中台不应复制 contact_mobile、身份证/信用代码、银行账号、密码等字段。客户投影只需要客户 ID、展示名称、账号状态、业务版本和同步时间。

客户与账号

新增客户时,customer_info.id 使用雪花 ID并尝试以同一个 ID 创建 sys_user.user_id

customer_info.id = sys_user.user_id
sys_user.user_type = customer

但账号创建失败只记录日志,不阻断客户保存,因此该关系不是天然完整的,必须进行覆盖率核验和补偿。

车辆与客户

2026-03-27 的 9a8e2a5f 提交将以下业务归属字段从 VehicleInfo 实体中移除:

  • customerId
  • contractCode
  • businessId
  • businessDeptId
  • contractType

代码注释明确这些字段改由 vehicle_lease_order_record 提供。因此不能再把 vehicle_info.customer_id 当作唯一权威口径,即使旧数据库或旧文档仍保留该列。

合同存在甲方客户和丙方客户,现有业务代码的有效客户规则为:

effectiveCustomerId = other_customer_id != null ? other_customer_id : customer_id

客户车辆范围还必须考虑交还车边界:只有已经交车且尚未还车的车辆,才能视为客户当前可见车辆。仅按 vehicle_lease_order_record.customer_id 查询会把已经归还的车辆继续授权给客户。

建议的当前客户车辆口径已调整为事务事实优先:

vehicle_info.del_flag = 0
AND vehicle_lease_order_record.del_flag = 0
AND effective_customer_id = 当前客户
AND 最新有效 delivery_vehicle.delivery_status IN (2,3)
AND 不存在该交车单对应的 return_vehicle_task.status IN (2,3,5)

vehicle_lease_order_record 只用于客户归属交叉校验,不使用 last_return_time 判断生命周期,因为还车草稿会提前写入该字段。生产影子查询已验证该条件,仍需由业务抽样确认换车、合同变更、丙方客户、重复交还车和历史补录场景。

订单记录的可信度限制

vehicle_lease_order_record 的设计目标是“每辆车一条当前记录”,但当前实现还不能未经校验就作为唯一授权依据:

  • VehicleLeaseOrderRecordMapper.xmlBaseResultMapBase_Column_List 没有 customer_idproject_name、交还车单 ID、交还车人等实体字段。调用 selectByVehicleIdselectByVehicleIds 等自定义查询时,这些字段会丢失。
  • saveOrUpdateForContract()deliveryVehicleId == null 时会清空已有交车和还车字段。合同提交、重新提交、审批通过等多条路径都会调用该方法,若车辆此前已经交付,可能暂时或永久破坏当前租赁状态。
  • 还车提交路径先写入还车时间,完成路径又可能清空当前合同和客户字段;不同查询不能仅以 customer_id IS NOT NULL 或仅以时间字段判断。
  • 交还车更新失败只记录日志、不中断主流程,业务任务成功不代表聚合记录一定成功同步。

因此阶段 A 需要同时以当前聚合表、历史表、交车单、还车任务和合同表交叉核对。正式的范围快照接口应在一个受测试的查询服务中封装口径,并对异常记录失败关闭,不能让各调用方直接读取聚合表自行解释。

4. 已发现的高风险缺口

P0现有客户车辆远程接口会返回全量车辆

RemoteVehicleService.listByCustomerId(customerId) 的客户过滤已被注释,当前实现实际查询全部未删除车辆;RemoteVehicleVo.customerIdcontractCode 的回填也被注释。

该接口在修复前不得用于任何外部客户权限,否则存在严重跨客户数据泄露风险。

P0客户账号体系尚不能直接用于车辆数据中台

  • customer_info 创建成功不代表 sys_user 一定创建成功。
  • 新客户账号没有分配角色或菜单权限。
  • sys_user.user_type=customer,但 UserType 枚举只识别 sys_userapp_user
  • Sa-Token 权限解析会调用 UserType.getUserType(),客户账号触发权限判断时可能抛出类型不存在异常。
  • 车辆数据中台当前只支持静态 Bearer Token 和 viewer/operator/adminPrincipal 中没有 customerIdtenantId 或 VIN 范围。
  • 客户账号创建复用了公开注册 RPC该 RPC受 sys.account.registerUser 开关控制。生产若关闭自助注册,客户档案仍会成功但账号创建必然失败。
  • 所有业务账号使用相同初始密码 ln123456,没有发现首次登录强制改密或一次性激活机制。外部客户上线前必须废弃该做法。
  • 通用密码登录按 tenantId + username 查询,不按 user_type 区分;客户编码必须在租户内与其他类型账号全局唯一,并需要防止账号类型混淆。

推荐新增“业务账号开通”内部能力,不再复用公开注册开关:

  1. (tenant_id, user_type, business_id) 幂等开通客户账号;business_id 对客户即 customer_info.id
  2. 同一事务或 Outbox 中完成账号、客户角色和业务绑定;失败可重试并可见,不再吞异常。
  3. 使用一次性激活链接或随机临时口令,首次登录强制设置密码;禁止共享默认密码。
  4. 登录成功后校验账号主体类型为 customer,并从服务端绑定关系取得 customerId
  5. 客户停用、合作终止、账号删除时撤销会话并让车辆中台短时声明快速失效。
  6. 存量补偿任务只处理缺失/异常账号,输出成功、冲突、跳过清单,不覆盖现有密码。

P0OneOS 地图和车辆查询没有客户级数据隔离

  • MapTruckController 的列表、搜索、详情和信息树均未按客户过滤。
  • 地图 SQL 默认返回所有符合运营状态的车辆。
  • VehicleInfoMapper 仅声明业务部门数据权限;业务专员/主管的默认过滤逻辑当前被整体注释。
  • 客户账号既没有部门数据范围,也没有独立客户数据范围。

P1代码、文档和映射存在漂移

  • VehicleInfo 实体已移除客户和合同字段。
  • VehicleInfoMapper.xml 的基础 ResultMap 和字段清单仍包含旧字段。
  • docs/VehicleInfo.md 仍描述 vehicle_info.customer_id 并给出过时接口参数。
  • 部分详情服务明确把客户和合同字段设置为 null
  • RemoteContractMatchService.matchByVehicleAtTime 已处理交还车时间边界,但合同命中时直接返回 contract.customerId,没有采用丙方优先的有效客户规则。
  • VehicleLeaseOrderRecordMapper.xml 未完整映射实体字段,自定义查询取得的 customerId 等值可能为 null
  • 合同保存会重置交还车字段,而交还车聚合更新异常又不会阻断主流程,存在聚合状态与真实业务任务不一致的窗口。

P0车辆中台现有授权是“功能角色”不是“数据范围”

当前 Principal 只有 NameRole,鉴权中间件仅按 viewer/operator/admin 判断 HTTP 方法与功能权限。Store 接口和 SQL 构造器没有客户或 VIN ScopePrincipalFromContext 也只被用于写操作的审计 Actor。

这会产生以下具体越权面:

API 组 当前行为 客户开放前要求
监控、车辆、实时位置 全量查询,可按 VIN/车牌筛选 所有列表、汇总、点位、详情统一限定授权 VIN
轨迹、历史、原始帧、里程 接受调用方传入 VIN/关键字 先校验 VIN Scope再访问 MySQL/TDengine空范围返回空不返回全量
告警 告警列表只按业务筛选;详情直接按事件 ID 查询 列表和详情都通过事件 VIN 校验,越权统一返回 404
导出 任务没有 owner/customerId列表展示全局任务知道 ID 即可下载 任务固化创建者、客户、VIN Scope 和快照版本;列表/下载校验所有权
运维质量、接入管理、规则配置 只按 viewer/operator/admin 控制 外部客户主体默认禁止,不能因拥有 viewer 角色而开放
车辆档案写入、同步 管理员可写 仅内部管理员或受信同步服务可用,客户主体永远禁止

尤其是导出任务当前保存在全局 exports Map 和 jobs.jsonListHistoryExports() 不区分创建者,HistoryExportFile(id) 也不校验主体;告警详情同样存在按 ID 直接读取的问题。这两处在客户入口上线前必须按 P0 修复。

5. 推荐集成架构

身份链路

外部客户登录仍由 OneOS 管理OneOS 负责账号启停和密码策略。车辆数据中台不复制客户密码。

推荐两种方案,优先级如下:

  1. OneOS Gateway 验证 Sa-Token 后,向车辆数据中台转发由共享密钥签名的身份声明,包含 userIdcustomerIdtenantIdrole、过期时间和请求 ID。
  2. 车辆数据中台收到 OneOS Access Token 后,调用 OneOS 内部会话校验接口获得同样的身份声明。

禁止信任浏览器直接传入的 customerId、客户名或 VIN 列表。

车辆范围同步

OneOS 对外提供内部服务接口,返回客户当前授权车辆快照及版本:

{
  "customerId": 1001,
  "version": "2026-07-14T12:00:00.000Z",
  "vehicles": [
    {
      "vehicleId": 2001,
      "vin": "...",
      "plateNumber": "...",
      "operationStatus": "...",
      "modelName": "...",
      "brandName": "...",
      "contractId": 3001,
      "contractCode": "...",
      "projectName": "...",
      "scopeStartAt": "..."
    }
  ]
}

车辆中台保存只读投影,例如:

  • business_customer
  • business_customer_vehicle_scope
  • business_scope_sync_run
  • business_scope_audit

所有车辆 API 在 Store/SQL 层统一追加 VIN Scope不能逐个页面自行过滤也不能先查询全量后在前端过滤。

推荐把范围变成显式的 QueryScope 参数,而不是只放在 context.ContextStore 接口若没有 Scope 参数就无法编译从机制上减少新增查询忘记加权限的概率。MySQL 查询优先 JOIN 本地范围投影表TDengine 单车查询先做 VIN 授权检查,多车查询使用已授权 VIN 集合并设置数量上限。空 Scope 对外部客户必须恒等于“无数据”,绝不能解释为“不限制”。

数据请求原则

  • 身份声明决定客户 ID。
  • 客户 ID 决定 VIN Scope。
  • VIN Scope 再约束监控、车辆、轨迹、历史、里程、告警、导出和地图聚合查询。
  • 内部管理员可显式选择客户;外部客户不能覆盖身份中的客户 ID。
  • 当 Scope 服务不可用或同步数据过期时,外部访问应失败关闭,不得降级为全量数据。

6. 分阶段实施

阶段 A只读数据审计

  • 执行 oneos-readonly-audit.sql
  • 确认生产表结构是否仍有 vehicle_info.customer_id
  • 统计客户账号覆盖率、启用率、角色覆盖率。
  • 统计当前交付车辆的 VIN 完整率、客户完整率和客户档案匹配率。
  • 抽样验证丙方客户、换车、已还车和多合同场景。

验收:形成数据质量基线,业务负责人确认“当前客户车辆”的唯一口径。

阶段 B修复 OneOS 权威接口和账号能力

该阶段已停止:用户明确要求不修改 ln-asset-management 任何逻辑。以下内容仅保留为已知风险清单,不执行。

  • 修复 listByCustomerId,按有效客户和交还车边界查询。
  • 增加批量客户车辆快照接口,返回 VIN 和业务版本。
  • 统一有效客户规则,覆盖丙方客户。
  • 修复订单记录 Mapper 字段遗漏,并禁止合同更新覆盖已经发生的交还车事实。
  • 对范围异常记录给出隔离清单,不将不确定归属车辆授权给任何外部客户。
  • 补充客户账号类型、角色、启停和存量账号补偿。
  • 新增专用业务账号开通能力,移除共享默认密码和对公开注册开关的依赖。
  • 增加双客户越权测试。

验收:客户 A、B 的车辆集合互斥;已还车辆立即退出范围;接口默认失败关闭。

阶段 C车辆数据中台身份和 Scope 投影

  • 扩展 Principal加入主体类型、外部用户 ID、客户 ID 和租户 ID。
  • 增加 OneOS 身份校验或可信代理声明校验。
  • 建立客户与车辆范围投影、版本和审计表。
  • 在底层查询构建器统一注入 VIN Scope。
  • 覆盖监控、车辆、轨迹、历史、统计、告警、导出、地图聚合和反向地理编码相关入口。

验收:任何 URL 参数、VIN 搜索、批量接口和导出均不能越权Scope 过期时外部请求拒绝访问。

阶段 D客户门户和入口

  • 外部子域名提供独立登录页。
  • 内部 OneOS 菜单以新标签页进入车辆数据中台。
  • 外部页面隐藏接入配置、运维质量和管理型功能。
  • 客户页默认展示授权车辆数量、实时地图、轨迹和里程统计。

验收:内部入口统一,外部入口独立;账号停用后现有会话及时失效。

阶段 E历史里程补录

  • 定义补录文件格式和来源平台。
  • 以 VIN、自然日、来源和导入批次保证幂等。
  • 导入约 20 天缺失里程并输出成功、冲突、缺 VIN 和异常跳变报告。
  • 不伪造无法取得的历史轨迹,页面明确轨迹数据起始时间。

验收:补录前后总量可对账,重复导入不重复累计,每条补录记录可追溯。

7. 需要修改 OneOS 前必须同步的范围

预计至少涉及以下模块,尚未进行任何修改:

  • ln-asset-management/ln-asset-api
  • ln-asset-management/src/main/java/com/ln/asset/api/impl/RemoteVehicleServiceImpl.java
  • ln-asset-management 的车辆/合同 Mapper 与 Service
  • ln-cloud/ruoyi-common-core 的用户类型定义
  • ln-cloud/ruoyi-auth 的客户登录策略
  • ln-cloud/ruoyi-system 的客户账号角色和状态管理
  • 可能新增 OneOS 内部 HTTP API、数据库索引和菜单脚本

修改前需要先同步具体文件、接口契约、SQL 变更、兼容方案、回滚方案和测试范围。