unis_crm/系统审计分析报告.md

144 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# UNIS CRM 系统全量审计分析报告
- 审计日期2026-09-01
- 审计范围后端Spring Boot + MyBatis、前端frontend / frontend1 两个 React 工程、SQL 脚本、Docker/Nginx 部署配置
- 审计方式:静态代码审查(未改动任何代码)
- 结论概览:商机/渠道/CRM 拓展互移、商机 tab 阶段筛选导出等核心业务逻辑**正确**;但存在 **2 个越权类安全漏洞、1 个前端业务阻断缺陷、1 个全新部署致命缺口** 及若干配置/一致性问题,建议按优先级修复。
---
## 一、严重问题(建议优先修复)
### 1. 打卡照片 / 日报附件下载接口存在越权访问IDOR
- 位置:
- [WorkController.java#L152-L159](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/controller/WorkController.java#L152-L159)`GET /api/work/checkin-photos/{fileName}`
- [WorkController.java#L169-L176](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/controller/WorkController.java#L169-L176)`GET /api/work/report-attachments/{fileName}`
- [WorkServiceImpl.java#L468-L476](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/WorkServiceImpl.java#L468-L476)、[WorkServiceImpl.java#L506-L514](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/WorkServiceImpl.java#L506-L514)
- 问题:两个下载接口不接收 `X-User-Id`,服务层仅做了「目录穿越」校验(拒绝 `..`、`/`、`\`**未校验文件属主/数据权限**。文件名格式为 `{userId}-{uuid}.{ext}`(见 [WorkServiceImpl.java#L462](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/WorkServiceImpl.java#L462)、[WorkServiceImpl.java#L495](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/WorkServiceImpl.java#L495))。任何已登录用户只要拿到/猜到他人文件名(文件名含 userId 前缀,可枚举)即可下载其打卡照片和日报附件。
- 建议:下载时校验文件前缀 userId 与当前登录用户一致,或通过数据权限服务校验归属。
### 2. 生产配置硬编码大量敏感凭据,且 jwt-secret 使用默认值
- 位置:[application.yml#L4-L10、L20-L29、L53、L78、L88](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/resources/application.yml#L4-L10)、[application-prod.yml#L51](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/resources/application-prod.yml#L51)
- 问题:
- MinIO`admin/Admin@123456`、PostgreSQL`unis@123`、Redis`zghz@123`)、企微 secret、OMS api-key 全部明文写入仓库。
- 两个 profile 的 `jwt-secret` 均为默认值 `change-me-please-change-me-32bytes`,且 docker-compose 未通过环境变量覆盖([docker-compose.yml#L14-L16](file:///Users/kangwenjing/Downloads/crm/unis_crm/docker-compose.yml#L14-L16) 仅传 `TZ``SPRING_PROFILES_ACTIVE`)。一旦使用默认值,攻击者可伪造任意用户/租户的 access token。
- 建议:改为注入环境变量/密钥管理,强制覆盖 `jwt-secret`
### 3. 日报提交失败后前端永久锁死,需刷新页面才能恢复
- 位置:[Work.tsx#L2175-L2226](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/src/pages/Work.tsx#L2175-L2226)
- 问题:`reportSubmitInFlightRef.current = true` 与 `setReportSubmitLocked(true)` 在 [L2205-L2206](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/src/pages/Work.tsx#L2205-L2206) 设置,但只在**成功路径**L2214-L2215复位。一旦 `saveWorkDailyReport` 抛错网络异常、后端校验失败、401 等),两个标记永久保持 `true`,提交按钮被守卫 [L2176](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/src/pages/Work.tsx#L2176) 永久禁用,提示「提交未确认,请刷新后重试」。当日已填写的整份日报(行项/附件/明日计划)必须刷新页面才能再次提交,丢失风险高。
- 建议:将两个标记的复位移入 `catch``finally`(与 `setSubmittingReport(false)` 一起)。
### 4. 全新安装脚本 `init_full_pg17.sql` 缺少 4 张运行时依赖表
- 位置:[init_full_pg17.sql](file:///Users/kangwenjing/Downloads/crm/unis_crm/sql/init_full_pg17.sql)(自声明为全新环境权威初始化入口)
- 问题:该脚本**没有**创建以下后端实际依赖的表:
- `crm_crm_expansion` / `crm_crm_expansion_contact`CRM 拓展主/从表,见 [CrmExpansionMapper.xml](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/resources/mapper/expansion/CrmExpansionMapper.xml)
- `crm_oms_dict_mapping`OMS 字典映射,见 [CrmOmsDictMappingMapper.xml](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/resources/mapper/CrmOmsDictMappingMapper.xml)
- `crm_channel_expansion_coverage`(覆盖地市从表,见 [ExpansionMapper.xml#L106-L119](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/resources/mapper/expansion/ExpansionMapper.xml#L106-L119)
- 这 4 张表只存在于增量脚本 [20260827.sql#L45、L77、L92、L142](file:///Users/kangwenjing/Downloads/crm/unis_crm/sql/20260827.sql#L45);已核实 8 个启动期 SchemaInitializer **均未补建**[common/](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/common/) 下只有 dashboard/日历/日报提醒/语音/数据权限等表)。
- 影响:全新库只跑 `init_full_pg17.sql`CRM 拓展模块、商机 OMS 推送/回传、渠道覆盖地市会在运行时抛 `relation does not exist`。生产库(已执行 20260827.sql不受影响但属部署链路硬缺口。
- 建议:在 `init_full_pg17.sql` 中补齐这 4 张表(可直接并入 20260827.sql 的定义)。
### 5. OMS 集成回写的阶段/状态校验与新阶段码不一致(残留死代码,不阻断实际同步)
- 位置:[OpportunityServiceImpl.java#L920-L925](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/OpportunityServiceImpl.java#L920-L925)、[OpportunityServiceImpl.java#L944-L974](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/OpportunityServiceImpl.java#L944-L974)
- 已确认用户核实OMS 反写只根据 `archived` 字段触发「已签约」,**不下发 `status=won/lost`**。因此 `archived=true → 强制 stage=S5` 路径([L922-L925](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/OpportunityServiceImpl.java#L922-L925))实际可正常同步「已签单」,**不构成阻断**。
- 残留问题(低危):
- `resolveIntegrationStatus` 仅识别字面量 `"won"`/`"lost"` 阶段,但阶段经 `mapStageToCrm` 映射后为 `S5`/`L`,这两个分支是**死代码**`WON_STAGE_CODES = Set.of("won","S6")`[L65](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/OpportunityServiceImpl.java#L65))定义后从未使用,且 `S6` 实为 OMS 码,佐证旧逻辑未随阶段码迁移同步更新。
- 若 OMS 未来开始下发 `status=won/lost`,仍会走到 `switch``case "won","lost"` 抛错;若 OMS 下发 `stage`(如 `L`)但不带 status商机 `status` 会落为 `active`(语义不符,但 `crm_opportunity.status` 允许 `active`,不报错)。
- 建议:后续可在 `resolveIntegrationStatus` 中按映射后新码S5→won、L→lost推导 status并清理死代码 `WON_STAGE_CODES`;非阻塞,可留作低优先维护项。
---
## 二、业务逻辑问题
### 6. 打卡可重复提交(当日无去重)
- 位置:[WorkServiceImpl.java#L324-L355](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/WorkServiceImpl.java#L324-L355)
- 问题:`saveCheckIn` 每次直接 `insertCheckIn`,未先查当日是否已有记录;`updateCheckIn`[WorkMapper.java#L94](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/mapper/WorkMapper.java#L94))为从未调用的死代码;打卡表当日索引非唯一([WorkCheckInSchemaInitializer.java#L37](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/common/WorkCheckInSchemaInitializer.java#L37))。双击/重试会产生多条当日打卡,统计重复。
### 7. 日报导出按「业务类型」筛选在 5000 条截断之后执行
- 位置:[WorkServiceImpl.java#L316-L321](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/WorkServiceImpl.java#L316-L321)
- 问题:`exportDailyReports` 先合并去重并 `limit(EXPORT_LIMIT=5000)`,再用内存 `hasReportLineOfType` 过滤;而打卡导出的 `bizType` 是在 SQL 内过滤([WorkMapper.xml#L35-L37](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/resources/mapper/work/WorkMapper.xml#L35-L37))。日期区间大、其它类型行数多时,目标类型日报会被 5000 上限截断,导出结果偏少/为空。
### 8. 打卡日期边界使用 DB `current_date`,与日报 Asia/Shanghai 口径不一致
- 位置:[WorkMapper.xml#L96、L720、L744](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/resources/mapper/work/WorkMapper.xml#L96)
- 问题:打卡按 `checkin_date = current_date`(依赖 DB 会话时区),日报统一用 Asia/Shanghai[WorkServiceImpl.java#L372-L373](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/WorkServiceImpl.java#L372-L373))。若 DB 服务器时区非上海,北京时间凌晨 0-8 点打卡的归属日期会错位。
### 9. Dashboard「当前阶段」硬编码旧枚举与商机/拓展新阶段码不一致
- 位置:[DashboardMapper.xml#L186-L194商机、L247-L254销售、L307-L314渠道](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/resources/mapper/dashboard/DashboardMapper.xml#L186-L194)
- 问题:`case o.stage when 'initial_contact'...'won'/'lost'` 已与新版字典码值S0/S1/S2/S3/S4/S5/L见 [20260828update.sql](file:///Users/kangwenjing/Downloads/crm/unis_crm/sql/20260828update.sql))脱节,首页动态会直接显示原始码(如 `S5`、`L`)。建议改为动态 join `sys_dict_item/sj_xmjd`
### 10. 跟进记录新增接口返回的 ID 是「影响行数」而非真实主键
- 位置:[OpportunityServiceImpl.java#L315-L327](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/OpportunityServiceImpl.java#L315-L327)、[ExpansionServiceImpl.java#L497-L506](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/ExpansionServiceImpl.java#L497-L506)
- 问题:`insertOpportunityFollowUp` / `insertExpansionFollowUp` 未配置 `useGeneratedKeys``inserted` 恒为 1接口返回的 `Long` 实际是行数而非跟进记录 ID。前端当前未依赖该 ID影响较低但属错误返回值。
### 11. 商机导出采用「全量拉取 + 前端过滤」
- 位置:[Opportunities.tsx#L2255](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/src/pages/Opportunities.tsx#L2255)
- 问题:导出调用 `getOpportunityOverview("", undefined, false, null, ...)``limit=null` 一次性拉取租户内全部商机再在客户端过滤。商机规模大时单次请求体量大、耗时长,存在超时/内存风险。建议改为服务端筛选或分批拉取。
### 12. 语音识别配置页缺少「未选租户」防护
- 位置:[speech-recognition-settings/index.tsx#L156、L201-L217](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend1/src/features/speech-recognition/pages/speech-recognition-settings/index.tsx#L156)
- 问题未选租户时保存会落到全局租户0静默改写全局配置而日报提醒页有 `isTenantUnselected` 拦截([report-reminder-settings/index.tsx](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend1/src/features/report-reminder/pages/report-reminder-settings/index.tsx))。行为不一致。
### 13. 前端 `request()` 与 `fetchWithAuth()` 对 401 处理不一致
- 位置:[auth.ts#L1259-L1271](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/src/lib/auth.ts#L1259-L1271) vs [auth.ts#L1298-L1311](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/src/lib/auth.ts#L1298-L1311)
- 问题:`request()` 遇 401 直接 `handleUnauthorizedResponse()`(清登录态跳登录页),不做「刷新+重试」;`fetchWithAuth()` 会先刷新再重试。token 被提前吊销或服务端判定失效但本地未过期时,用户会在操作中被直接登出并丢失已输入内容。
### 14. 附件上传走 XHR 但未做 token 主动刷新
- 位置:[auth.ts#L1668-L1723](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/src/lib/auth.ts#L1668-L1723)
- 问题:`uploadWorkReportAttachment` 直接读 `localStorage.accessToken` 发 XHR不经过 `ensureFreshAccessToken`。长时间编辑后 token 到期,上传 401 → 直接登出,正在填写的日报/打卡表单数据丢失。建议上传前先刷新 token。
---
## 三、潜在风险 / 代码规范
| # | 问题 | 位置 |
|---|------|------|
| 15 | 生产环境 MyBatis `log-impl: StdOutImpl` 打印全部 SQL 与绑定参数(含敏感数据) | [application.yml#L36](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/resources/application.yml#L36) |
| 16 | 语音转写整文件读入内存、无独立大小限制;打卡照片无大小限制(依赖全局 500MB可致 OOM/存储膨胀 | [WorkServiceImpl.java#L516-L573](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/WorkServiceImpl.java#L516-L573)、[WorkServiceImpl.java#L448-L465](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/WorkServiceImpl.java#L448-L465) |
| 17 | 定时任务共享默认单线程调度器,`ReportReminderScheduler`(每分钟)与 `BusinessCalendarAutoSync`(每日 3:15可能相互阻塞且无分布式锁 | [ReportReminderScheduler.java](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/ReportReminderScheduler.java)、[BusinessCalendarAutoSync.java](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/BusinessCalendarAutoSync.java) |
| 18 | 数据权限完全依赖 unisbase 插件在 SQL 上动态注入SQL 本身无兜底条件;插件缺失/非 Web 上下文可能返回全库数据 | [WorkMapper.java#L32-L72](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/mapper/WorkMapper.java#L32) |
| 19 | 前端权限判断 fail-open权限码列表为空时全部放行`if (!codes.length) return true`),权限拉取失败时 UI 虚假放行 | [auth.ts#L1469-L1483](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/src/lib/auth.ts#L1469-L1483) |
| 20 | `20260828update.sql``UPDATE ... FROM crm_oms_dict_mapping` 依赖 `oms_value` 唯一,但表唯一约束为 `(dict_type, crm_value, oms_value)`,未约束 `(dict_type, oms_value)` 唯一,后续新增映射可能产生非确定性更新 | [20260828update.sql#L106-L112](file:///Users/kangwenjing/Downloads/crm/unis_crm/sql/20260828update.sql#L106-L112)、[20260827.sql#L104](file:///Users/kangwenjing/Downloads/crm/unis_crm/sql/20260827.sql#L104) |
| 21 | 生产 profile 企微默认 `enabled:false`,与 SSO 期望redirect-uri 指向 crm.unissense.top不一致`/api/wecom/sso/**`、`/api/opportunities/integration/**` 为 permit-all | [application-prod.yml#L72-L82](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/resources/application-prod.yml#L72-L82) |
| 22 | frontend1 `http.ts` 鉴权白名单用 `url.includes(path)` 子串匹配,路径匹配过度放宽 | [http.ts#L14、L68-L70](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend1/src/api/http.ts#L14) |
| 23 | 生产 MinIO `endpoint``https://miniodown.nex.unisspace.com``use_ssl: false`,可能连接异常 | [application-prod.yml#L5-L10](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/resources/application-prod.yml#L5-L10) |
| 24 | 后端 Dockerfile 复制 `target/unis-crm-backend-1.0.0-SNAPSHOT.jar`,但仓库内 jar 位于 `backend/` 根目录(非 target/),依赖 CI 先执行 `mvn package`,否则 `docker compose build` 会失败 | [backend/Dockerfile#L7](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/Dockerfile#L7) |
| 25 | 打卡/日报元数据使用字符串内嵌标记(`[[CHECKIN_PHOTOS]]`、`[[WORK_REPORT_LINES]]` 等)拼入 remark 字段,解析依赖精确格式,健壮性差 | [WorkServiceImpl.java#L91-L102](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/WorkServiceImpl.java#L91-L102) |
| 26 | `ActionDialog` 确认回调 `void onConfirm()` 未捕获 rejection | [ActionDialog.tsx#L150](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/src/components/ActionDialog.tsx#L150) |
| 27 | 腾讯地图生产 Key 硬编码进前端源码作兜底 | [tencentMap.ts#L1](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/src/lib/tencentMap.ts#L1) |
| 28 | 移动端多选下拉点击遮罩关闭不「回滚」已勾选项,与常规确定/取消交互不一致,易误改覆盖省市 | [AdaptiveSelect.tsx#L204-L216](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/src/components/AdaptiveSelect.tsx#L204-L216) |
| 29 | 浏览器定位最坏路径约 33s弱信号下用户易误以为卡死 | [tencentMap.ts#L145-L176](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/src/lib/tencentMap.ts#L145-L176) |
| 30 | Dashboard 权限/消息加载静默吞异常,问题被掩盖 | [DashboardServiceImpl.java#L171-L207](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/DashboardServiceImpl.java#L171-L207) |
---
## 四、已核对且判定为正常的重点项
1. **商机 tab 阶段筛选/导出约束(与项目硬约束一致)**
- 未签单 tab`excludeStageCodes=lostStageCodes`(排除 L-已丢单)✓([Opportunities.tsx#L2254](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/src/pages/Opportunities.tsx#L2254)、后端 [OpportunityMapper.xml#L288-L294](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/resources/mapper/opportunity/OpportunityMapper.xml#L288-L294)
- 已丢单 tab`stageCodes=lostStageCodes`
- 切换 tab 重置阶段筛选 ✓([Opportunities.tsx#L1718-L1725](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/src/pages/Opportunities.tsx#L1718-L1725)
- 阶段选项动态取自 `sys_dict_item/sj_xmjd`,未硬编码 ✓
2. **渠道拓展/CRM 拓展互移流程**:属主校验、字段映射(覆盖省市/办公地址/联系人)、跟进/签到/日报消息的 biz_type 迁移、旧记录清理均正确([ExpansionServiceImpl.java#L398-L495](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/ExpansionServiceImpl.java#L398-L495)),与前端弹窗字段、校验一致。
3. **覆盖地市存储模型**:后端读写 `crm_channel_expansion_coverage` 从表([ExpansionMapper.xml#L106-L119](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/resources/mapper/expansion/ExpansionMapper.xml#L106-L119)`insertChannelExpansion` 不引用废弃的 coverage 列,与 20260827.sql 的设计一致 ✓
4. **商机集成 archived→S5 强制**:已实现并通过单测([OpportunityServiceImplTest.java#L211-L228](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/test/java/com/unis/crm/service/impl/OpportunityServiceImplTest.java#L211-L228));且经确认 OMS 反写仅用 `archived` 字段触发「已签约」(不下发 `status=won/lost`),实际同步正常 ✓
5. **SQL 增量脚本幂等性**`create table if not exists`、`drop constraint if exists`、`on conflict do nothing/update` 均正确20260828update.sql 的换算用单条 UPDATE 避免连环转换 ✓
6. **前后端字段一致性**`MoveCrmToChannelRequest`coverageProvince/coverageCity/coverageItems、`CreateOpportunityRequest` 与前端序列化一致confidencePct 正则与前端兜底一致 ✓
7. **Nginx 延迟解析**:两个前端 nginx 均使用 `resolver + set $backend_host` 延迟解析域名,符合约束 ✓([default.conf.template#L8、L16-L19](file:///Users/kangwenjing/Downloads/crm/unis_crm/frontend/nginx/default.conf.template#L8)
8. **前端 Dockerfile/.dockerignore**`.dockerignore` 已排除 node_modules、.git、系统目录多阶段构建合理 ✓
9. **日报保存逻辑**:「当日重复提交→更新」「北京时间 10 点前归属前一天」「提醒在事务提交后触发」均正确([WorkServiceImpl.java#L357-L415](file:///Users/kangwenjing/Downloads/crm/unis_crm/backend/src/main/java/com/unis/crm/service/impl/WorkServiceImpl.java#L357-L415)
---
## 五、修复优先级建议
| 优先级 | 问题编号 | 理由 |
|--------|---------|------|
| P0 | #1、#2 | 越权与凭据泄露,安全风险最高 |
| P0 | #4 | 全新部署直接功能瘫痪 |
| P1 | #3 | 前端业务阻断,日报当天无法提交 |
| P2 | #6、#7、#8、#9、#11、#13、#14 | 数据正确性与一致性 |
| P3 | #5 及其余 | #5 已确认不阻断实际同步OMS 仅用 archived 反写),降为低危维护项 |
> 说明:本报告仅做静态审计,未运行代码;部分结论(如 #5 是否实际触发、#11 的量级、#8 的时区)建议结合运行时数据/日志复核后再修复。