# OneOS 与 ln-asset-management 系统分析

更新时间：2026-07-14  
分析方式：源码静态分析、生产数据库只读元数据与聚合核验  
修改边界：本报告未修改 `/Users/lingniu/project/ai-coding/oneos`。用户已明确要求不修改 `ln-asset-management` 任何逻辑；所有建议均需另行同步和批准。

## 1. 结论先行

`ln-asset-management` 不是单一车辆档案服务，而是 OneOS 的资产和车辆业务单体，覆盖车辆主档、租赁合同、交车、还车、换车、应收、结算、保险、证照、异常异动、维修故障、加氢、备件、培训、消息与工作台等领域。车辆数据中台不能把它当作实时遥测服务，也不能直接把它的现有 REST/Dubbo 接口公开给客户。

推荐的系统职责是：

- OneOS：车辆业务身份、客户、合同、交还车、业务状态的权威来源；
- 车辆数据中台：TDengine/Redis/Kafka 中遥测、轨迹、在线状态、告警和分析的权威来源；
- 两者之间：使用最小权限只读快照，不在客户请求链路上实时查询 OneOS，不信任客户端传入的客户 ID；
- 当前客户车辆生命周期：以完成的 `delivery_vehicle` 和 `return_vehicle_task` 事务事实判断，`vehicle_lease_order_record` 仅用于客户归属交叉校验。

当前不能安全公开 OneOS 接口，主要原因包括：

1. `RemoteVehicleService.listByCustomerId` 当前忽略客户 ID，存在返回全量车辆风险；
2. 网关能证明“已登录”，但 93 个业务 Controller 中只有 1 个检出细粒度权限注解，不能证明接口级或客户级授权完整；
3. 全局 API 日志拦截器会记录请求头、请求体和响应体，且未像注解切面一样脱敏 Authorization、Token 和 Cookie；
4. 注解接口同时被全局拦截器与 `@ApiLog` 切面记录，存在重复日志；两个月日志表约占生产库数据体积 83%；
5. 租赁聚合表会被合同保存和还车草稿等非最终业务动作影响，不能单独作为授权真值；
6. 核心交车、还车和合同类达到 2,700～6,000 行，自动化测试没有覆盖核心生命周期；
7. 24 个定时任务未发现分布式锁，服务多副本部署存在重复执行风险。

## 2. 仓库与运行架构

`/Users/lingniu/project/ai-coding/oneos` 下是四个独立 Git 仓库，而不是一个单仓：

| 仓库 | 主要职责 | 与车辆数据中台关系 |
| --- | --- | --- |
| `ln-cloud` | RuoYi Cloud 网关、认证、用户、组织、字典、资源、工作流、Nacos 等 | 身份和组织来源；外部客户身份尚未建立 |
| `ln-asset-management` | 车辆和资产全生命周期业务 | 车辆业务主档和客户 Scope 来源 |
| `ln-energy-v2` | 能源及财务类远程能力 | OneOS 内部依赖，不作为遥测主源 |
| `ln-ocr` | OCR 能力及共享 API | 保险、证照等业务依赖 |

`ln-asset-management` 技术基线：

- Java 21；Spring Boot 3.5.10；Spring Cloud 2025.0.0；
- MyBatis-Plus 3.5.15，MySQL Connector/J 9.5；
- Nacos 配置与注册、Dubbo 服务、Sa-Token、RabbitMQ、异步和定时任务；
- 主服务端口 8701，网关路由 `/asset/**` 后去除一层前缀；
- Dockerfile 默认 `test` profile，生产实际配置依赖 Nacos 覆盖；
- Maven 依赖公司私有 SNAPSHOT 包，本机缺少仓库凭证时构建会在依赖解析阶段收到 401；
- 仓库没有发现 Maven Wrapper、CI 工作流、docker-compose 或完整生产运行手册。

源码规模基线：

| 指标 | 数量 |
| --- | ---: |
| Java 代码 | 约 181,425 行 |
| 业务 Controller | 93 个（按源码注解统计；命名扫描为 95 个） |
| 显式 HTTP 方法 | 约 815 个 |
| Mapper | 约 161 个 |
| `@TableName` 实体映射 | 158 个 |
| Dubbo 服务实现 | 20 个 |
| 含 Dubbo 引用的文件 | 85 个 |
| 定时任务文件 | 24 个 |
| 测试文件 | 30 个、约 4,372 行 |

## 3. 业务领域清单

### 3.1 车辆主档与运营状态

模块路径存在历史拼写 `modules/vihicle`，但它是车辆核心模块，共 11 个 Controller、约 107 个 HTTP 方法。

主要能力：

- `VehicleInfoController`：车辆档案、查询、导入导出；
- `VehicleModelController`：车型；
- `VehicleRealtimeLocationController`：OneOS 内部实时位置投影；
- `PrepareCarController`：备车；
- `VehicleLicenseController`、批量上牌：证照和上牌；
- `VehicleTransferController`：调拨；
- `AftermarketDeviceController`：后装设备；
- `AccidentInfoController`：事故；
- `VehicleCheckItemController`、`VehicleMaintenanceItemController`：检查和维保配置。

主要表：`vehicle_info`、`vehicle_model`、`vehicle_status`、`vehicle_realtime_location`、`prepare_car`、`vehicle_transfer`、`vehicle_license`、`aftermarket_device`、`accident_info`、`tab_data_attachment` 等 19 张显式映射表。

权威性判断：

- 车辆身份以 `vehicle_info.id` 和标准化 VIN 为主；
- 车牌会变化，不能作为跨系统唯一键；
- `vehicle_status` 是 OneOS 业务运营状态，不等于车联网在线状态；
- `vehicle_realtime_location` 和地图同步表是 OneOS 的展示投影，实时遥测仍应以车辆数据中台 Redis/TDengine 为准；
- `vehicle_info.customer_id` 不是可靠客户归属来源，客户关系需通过合同和交还车事实确定。

### 3.2 租赁合同、交车、还车和换车

`contract` 是最大领域：21 个 Controller、约 237 个 HTTP 方法、46 张显式映射表。

主要链路：

```text
客户/合同
  -> vehicle_lease_contract_info
  -> vehicle_lease_order / vehicle_lease_order_detail
  -> delivery_task_subject / delivery_vehicle
  -> 正式交车完成
  -> 客户当前持有车辆
  -> return_vehicle_task 或 vehicle_replacement
  -> 正式还车/换车完成
  -> 应收、还车付款、还车结算、发票
```

关键事实表：

- 合同：`vehicle_lease_contract_info`、`vehicle_lease_contract_log`；
- 合同车辆：`vehicle_lease_order`、`vehicle_lease_order_detail`；
- 交车：`delivery_task_subject`、`delivery_vehicle`、`delivery_vehicle_check_item`；
- 还车：`return_vehicle_task`、`return_vehicle_check_item`；
- 换车：`vehicle_replacement`；
- 当前聚合与历史：`vehicle_lease_order_record`、`vehicle_lease_order_record_log`；
- 财务：`receivable_*`、`return_payment*`、`return_settlement*`、`rental_invoice`。

当前客户车辆的安全口径：

```text
最新有效 delivery_vehicle.delivery_status IN (2, 3)
AND delivery_time IS NOT NULL
AND 不存在该交车单对应的有效 return_vehicle_task.status IN (2, 3, 5)
AND vehicle_info 有效且 VIN 非空
AND customer_info 有效
AND vehicle_lease_contract_info 有效
AND vehicle_lease_order_record.customer_id
    = COALESCE(contract.other_customer_id, contract.customer_id)
AND 同一车辆和标准化 VIN 不存在多个当前关系
```

不能仅使用 `vehicle_lease_order_record.last_delivery_time/last_return_time`：还车草稿保存会提前写 `last_return_time`；合同保存也可能覆盖交还车聚合字段；部分聚合更新失败只记录日志。用户已要求不修改这些 OneOS 逻辑，因此车辆数据中台必须在读取侧绕开并失败关闭。

### 3.3 客户、司机与身份

- `customer_info`：业务客户档案；
- `driver_info`：司机档案、黑名单、手机号和证件；
- `ln-cloud/ry-cloud.sys_user`：登录账号；
- 业务客户 ID 与 `sys_user.user_id` 没有稳定映射，生产只读审计未发现可直接使用的客户账号体系；
- 手机号只能作为人工核对线索，不能自动建立授权关系；
- 合同有甲方和丙方客户，当前有效客户规则为 `COALESCE(other_customer_id, customer_id)`。

结论：车辆数据中台内部管理员可以继续使用独立平台令牌；外部客户入口在可信身份映射建立前不能开放。

### 3.4 地图与外部定位

`map` 模块有 5 个 Controller：字典、组织、站点、车辆和地理编码。

数据和依赖：

- `tab_truck_remote_sync_realtime_info`：车辆地图投影；
- `tab_outside_hydrogen_site`：站点投影；
- Hasp、远程实际车辆接口和高德 REST API；
- `MapSyncTask` 定期同步车辆与站点。

结论：OneOS 地图适合内部业务展示，不适合作为车辆数据中台遥测源。两套地图需要统一 WGS-84 到 GCJ-02 的显示转换，但原始存储坐标必须保留来源和坐标系标识。

### 3.5 资产后市场与合规

覆盖领域包括：

- 保险采购、保单、OCR：14 张表、约 69 个 HTTP 方法；
- 车辆异常异动：`vehicle_abnormal_move*`；
- 故障：`vehicle_fault_manage`；
- 年检、年审、车辆证书、交通违章；
- 维修站、救援队、检查站；
- 备件、出入库和仓库；
- 培训材料与培训记录。

这些业务可以消费车辆中台的里程、位置、在线、告警证据，但车辆中台不能反向改写合同、保险、证照、结算或事故事实。涉及锁车、控车的能力不在本分析和实施范围。

### 3.6 能源与工作流

- 加氢站、加氢台账、加氢场站、充电站；
- 消息、通知规则、待办任务和工作台；
- 通过 `RemoteWorkflowService`、`RemoteUserService`、`RemoteDictService`、`RemoteFileService` 等 Dubbo 服务依赖 `ln-cloud`；
- 定时生成账单、合同到期提醒、证照到期提醒、台账状态同步等。

## 4. 接口与安全边界

### 4.1 已有安全机制

- 网关 `AuthFilter` 对非白名单请求执行 `StpUtil.checkLogin()`；
- 微服务 `SecurityConfiguration` 可通过 Same-Token 验证请求是否由网关转发；
- actuator 使用 Basic Auth；
- 网关把 `/asset/**` 转发到 `ln-asset-management`。

这些机制只能证明请求已登录或来自网关，不能自动证明用户有某个业务动作权限，更不能证明客户只能访问自己的车辆。

### 4.2 接口级授权缺口

静态扫描 93 个业务 Controller，只有 1 个文件出现 `@SaCheckPermission` 等细粒度权限注解；另有 3 个 Controller/回调路径使用 `@SaIgnore`。部分数据权限由 Mapper/DataPermission 处理，但没有形成覆盖所有车辆、合同、地图和导出入口的统一客户 Scope。

因此：

- OneOS 现有 REST API 只能作为内部业务接口；
- 不能直接公网开放 8701；
- 不能把 `customerId` 查询参数或 `X-Customer-Id` 请求头当作授权身份；
- 车辆数据中台应在自身底层查询统一注入 VIN Scope，并对详情返回 404，避免泄漏对象存在性。

### 4.3 Dubbo 接口评估

`ln-asset-api` 暴露 20 个远程服务，包括车辆、客户、合同匹配、充电/加氢站、异常异动、保险、结算和任务等。

车辆数据中台当前不应直接调用 `RemoteVehicleService.listByCustomerId`：实现忽略客户 ID，并按有效车辆返回全量结果。可复用的 Dubbo 接口必须逐个做参数、范围、分页、超时和失败策略审计；RPC 不等于安全边界。

## 5. 数据库现状

生产只读元数据基线：

| 指标 | 结果 |
| --- | ---: |
| 基础表 | 448 |
| 数据体积 | 约 2.63 GB |
| 索引体积 | 约 381 MB |
| 有效车辆 | 1,209 |
| 当前事务事实候选车辆 | 639 |
| 可安全发布 Scope | 613 |
| 隔离关系 | 26 |

448 张表明显多于 158 个实体映射，因为数据库还包含历史表、BI 表、手工迁移表、备份表和动态月表。迁移、备份和运行表混放在同一业务库，增加容量、权限和误操作风险。

### 5.1 API 请求日志容量与隐私风险

`api_request_log_202606` 和 `api_request_log_202607` 合计约 2.19 GB，约占全库数据体积 83%。源码证据：

- `ApiLogWebConfig` 把全局拦截器挂到几乎所有业务路径；
- `ApiLogConfig` 默认记录参数、请求体、响应体和请求头；
- `ApiLogInterceptor.getRequestHeaders()` 不脱敏任何请求头；
- `ApiLogAspect.getRequestHeaders()` 会脱敏 Authorization/Token/Cookie，但仅用于 `@ApiLog` 切面；
- 带 `@ApiLog` 的接口同时被拦截器和切面保存，可能生成两条日志；
- 清理接口只删除“当前时间减保留天数所在月份”一张表内的旧行，并不会遍历或删除所有更早月表；异常被吞掉；
- `/api-request-log/clean` 没有细粒度权限注解。

这是 P0 安全和运维风险：日志可能包含登录凭证、身份证、手机号、合同、签章、附件地址和完整业务响应，并持续快速增长。

### 5.2 关键索引和约束

已确认：

- `vehicle_info` 有车牌索引，但 VIN 没有索引或唯一约束；
- `vehicle_lease_order_record.vehicle_id`、`vehicle_status.vehicle_id` 只有普通索引，没有唯一约束；
- `vehicle_lease_order_record.customer_id` 缺少 Scope 查询索引；
- `delivery_vehicle.vehicle_id` 和 `return_vehicle_task.delivery_vehicle_id` 已有普通/组合索引；
- 生产数据存在 1 组“一车多聚合记录”和大量聚合/历史差异，不能直接添加唯一约束。

任何清理、唯一约束或索引 DDL 都必须单独审批，不属于当前只读分析。

## 6. 可靠性与可维护性

### 6.1 超大类热点

| 文件 | 行数（约） | 风险 |
| --- | ---: | --- |
| `VehicleLeaseContractFullServiceImpl` | 6,082 | 合同、工作流、附件和聚合职责耦合 |
| `ReturnTaskServiceImpl` | 4,015 | 草稿、完成、签章、结算与聚合边界混合 |
| `ReturnSettlementServiceImpl` | 3,902 | 财务聚合复杂、回滚边界难验证 |
| `InsuranceProcurement2ServiceImpl` | 3,626 | OCR、任务、保单、附件和状态混合 |
| `HydrogenFuelLedgerServiceImpl` | 3,322 | 导入、匹配、财务状态耦合 |
| `VehicleTransferServiceImpl` | 3,268 | 调拨、车辆状态、工作流耦合 |
| `DeliveryTaskServiceImpl` | 2,715 | 交车事实和下游副作用耦合 |

测试集中在加氢、保险辅助逻辑、证照和少量 Mapper；没有覆盖合同保存、交车完成、还车草稿、还车完成、再次交车、丙方客户、换车等 Scope 核心用例。

### 6.2 事务和错误处理

106 个 `service/impl` 文件中约 63 个文件出现 `@Transactional`，但“存在注解”不代表跨 Dubbo、工作流、签章、文件和本地数据库具备原子性。核心链路存在捕获异常后只记日志、继续返回成功的模式，导致任务状态与聚合表可能不一致。

### 6.3 定时任务

源码有 24 个 `@Scheduled` 文件，应用主类全局启用调度，未发现 ShedLock 或等价分布式锁。若生产运行多个实例，账单生成、到期提醒、地图同步、证照状态同步等任务可能重复执行。部署前必须确认生产实例数和任务幂等性。

### 6.4 配置和交付

- `application.yml` 是 Git 跟踪文件，包含邮件、短信和第三方服务的凭证型配置项；部分值看起来不是纯占位符，必须在不打印原值的前提下轮换并迁到密钥管理/Nacos；
- README 只给出 Swagger 地址，没有依赖、构建、配置、迁移、部署、回滚、健康检查和故障处置说明；
- Dockerfile 默认测试环境，若生产变量遗漏可能连入错误命名空间；
- 私有 Maven 仓库凭证缺失会阻断可重复构建；
- 未发现 CI 门禁，无法证明每次发布都执行测试、依赖扫描和镜像校验。

### 6.5 可从源码推导的运维顺序

仓库没有 OneOS 专用生产运维手册，`ln-cloud/README.md` 基本是上游 RuoYi 框架说明，Nacos README 只有“复制配置”的一句提示。以下只能作为源码推导，不能替代生产值班手册：

1. 先启动 MySQL、Redis、Nacos，以及文件存储/资源服务所需基础设施；
2. 在对应 namespace/group 中准备 `application-common.yml`、`datasource.yml`、`ln-asset-management.yaml`；
3. 启动 `ruoyi-system`、`ruoyi-resource`、`ruoyi-workflow` 等被 Dubbo 引用的服务；
4. 启动 `ruoyi-auth` 和 `ruoyi-gateway`；
5. 最后启动 `ln-asset-management`，核验 Nacos 注册、Dubbo 引用、数据库、Redis、RabbitMQ、文件服务和 actuator；
6. 确认只有一个实例执行非幂等 `@Scheduled`，或先证明所有定时任务具备分布式幂等；
7. 再开放 `/asset/**` 流量，并检查错误率、Dubbo 超时、数据库连接池、API 日志增速和任务重复执行。

构建时应显式选择 profile，并避免 Maven package 阶段意外连接 Docker daemon：

```text
mvn -Pprod -Ddocker.skip=true clean package
```

该命令当前仍依赖公司私有 Maven 仓库凭证。Dockerfile 自带的 `SPRING_PROFILE_ACTIVE=test` 和 `NAMESPACE=test` 必须由生产环境显式覆盖；否则不能视为生产可部署制品。

生产运维说明仍缺少：真实部署拓扑、实例数、镜像仓库流程、Nacos 配置版本、SQL 迁移账本、备份恢复、发布回滚、健康检查阈值、告警接收人、日志保留和密钥轮换。未补齐前，不建议自动化改动或独立部署 OneOS。

## 7. 风险矩阵

| 等级 | 风险 | 当前处置 |
| --- | --- | --- |
| P0 | API 日志可能保存未脱敏认证头和大量敏感请求/响应 | 不改 OneOS；立即限制日志查询/清理接口访问，制定脱敏、保留和轮换方案后另行审批 |
| P0 | `listByCustomerId` 返回全量车辆 | 数据中台禁用该接口，使用只读事务事实快照 |
| P0 | 登录校验不等于业务/客户数据权限 | OneOS 不公开；数据中台统一执行 VIN Scope |
| P0 | 客户账号与业务客户没有可信映射 | 外部客户入口保持关闭 |
| P1 | 聚合生命周期被草稿/合同保存影响 | 读取交还车事务事实，聚合仅作交叉校验 |
| P1 | 关键业务异常被吞掉，状态可能不一致 | 快照失败关闭并隔离；上游修复需重新同步批准 |
| P1 | 多副本定时任务可能重复 | 上线前确认单实例或任务幂等/分布式锁 |
| P1 | VIN、聚合和状态缺少唯一约束 | 不直接 DDL；先清理异常并做影子验证 |
| P1 | 核心生命周期测试缺失 | 将合同/交还车/换车作为未来修改的强制回归门禁 |
| P1 | 凭证型配置进入源码 | 安全轮换和密钥迁移需单独紧急流程 |
| P2 | 超大类、命名和 URL 漂移 | 分领域抽取应用服务，保持兼容接口 |
| P2 | 运维文档与 CI 缺失 | 补齐构建、发布、回滚、监控和演练说明 |

## 8. 对车辆数据中台的可复用与禁止清单

### 可只读复用

- `vehicle_info`：VIN、车牌、车型和主档；
- `vehicle_model`：车型能力和显示配置；
- `vehicle_status`：OneOS 业务运营状态；
- `customer_info`、`vehicle_lease_contract_info`：客户和合同；
- `delivery_vehicle`、`return_vehicle_task`：当前持有生命周期；
- 停车场、站点、司机等低频主数据；
- 所有读取都通过专用表级 SELECT 账号和周期快照。

### 不作为权威来源

- OneOS 地图投影中的在线状态、位置和里程；
- `vehicle_info.customer_id`；
- 单独的 `vehicle_lease_order_record.last_return_time`；
- `vehicle_lease_order_record_log` 最大 ID；
- 客户手机号与系统用户手机号的自动匹配；
- 客户请求参数中的客户 ID。

### 禁止回写

- 合同、交车、还车、换车；
- 锁车、控车；
- 保险、事故、违章、证照、结算和发票；
- OneOS 用户和客户归属；
- 任何生产数据修复或 DDL，除非用户另行明确批准。

## 9. 分阶段建议

### 阶段 A：只读基线（已完成）

- 仓库和模块清单；
- 生产表规模、车辆/客户/Scope 数据质量；
- 生命周期和权限风险；
- OneOS 保持零修改。

### 阶段 B：车辆数据中台只读投影（代码已准备，尚未部署）

- 专用只读账号只授予 7 张必要表 SELECT；
- 两分钟一次读取交还车事务事实；
- 613 条安全关系发布，26 条隔离；
- 内容寻址版本、事务整体切换、异常比例门禁；
- ECS 当前仍缺 `ONEOS_MYSQL_DSN`、平台迁移 012 和同步 timer。

### 阶段 C：客户身份与 API Scope（未完成）

- 明确可信客户身份来源；
- 平台 Principal 增加主体类型和客户 ID；
- 对监控、车辆、轨迹、历史、统计、告警、导出和地图统一注入 Scope；
- 完成双客户越权测试后才允许灰度。

### 阶段 D：OneOS 风险治理（未获授权）

如用户未来批准，应优先按独立批次处理：

1. API 日志脱敏、去重、保留策略和访问权限；
2. 客户车辆 RPC 失败关闭；
3. 聚合写入的事务与生命周期边界；
4. 定时任务幂等或分布式锁；
5. 凭证轮换、构建和运维门禁。

每个批次都必须先同步文件、行为变化、数据库影响、测试和回滚方案，不与数据修复或 DDL 混合发布。

## 10. 证据索引

- 系统集成与 Scope：`docs/oneos-integration-analysis.md`；
- 生产只读审计：`docs/oneos-production-audit-report.md`；
- 业务影响：`docs/oneos-business-impact-matrix.md`；
- 客户 API 覆盖：`docs/customer-scope-api-enforcement-matrix.md`；
- Scope 契约：`docs/oneos-customer-vehicle-scope-contract.md`；
- OneOS 网关认证：`ln-cloud/ruoyi-gateway/.../AuthFilter.java`；
- 微服务 Same-Token：`ln-cloud/ruoyi-common/ruoyi-common-security/.../SecurityConfiguration.java`；
- 全局 API 日志：`ln-asset-management/src/main/java/com/ln/asset/common/log/`；
- 租赁生命周期：`ln-asset-management/src/main/java/com/ln/asset/modules/contract/`；
- 车辆主档：`ln-asset-management/src/main/java/com/ln/asset/modules/vihicle/`；
- 远程接口：`ln-asset-management/ln-asset-api/src/main/java/com/ln/asset/api/`。
