Files
platforms/docs/平台总后台审计报告-2026-07-27.md

67 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 平台总后台审计报告2026-07-27
## 范围与结论
本次审计覆盖 46 个平台后台资源33 个可写资源、12 个只读资源和 1 个仅追加的安全事件处置资源。后端资源契约现同时声明领域、资源名、HTTP 路径、页面类型和读写模式,并由运行时注册路由生成清单。前端审计据此逐项校验后端路由、前端资源声明、实际加载的页面组件和带菜单元数据的路由;任一层缺失均以 `领域/资源: missing <layer>` 失败。
终审追加识别的 8 项 Important 问题已全部处置并纳入回归验证:创建响应安全投影、轨迹点精确位置授权、关键字筛选一致性、表单字段类型、空可选关系、审批动作、树节点归档,以及 Biome/模型中文注释完整性。终审后复核又关闭 4 项 ImportantJSONB 字符串绑定、日期 RFC3339 边界、编辑密码语义,以及创建响应与关键字查询的显式安全白名单。
## 发现与处置
| 发现 | 处置 | 验证 |
| --- | --- | --- |
| 只读页面的静态检查未覆盖状态变更调用 | 将 `resourceApi.updateStatus` 纳入只读页的变更操作集合,同时覆盖 create、update、archive | `audit-check.test.mjs` 的只读页用例 |
| 前端资源与后端路由只按资源名和文件名进行粗略匹配 | `ResourceContract.Path` 成为唯一后端路径声明;审计逐项校验 GET/POST/PUT/PATCH/DELETE按资源模式以及资源路径一致性 | Go 的 `TestEveryContractHasRegisteredRoute``pnpm audit:platform` |
| 页面存在但未被菜单路由实际加载时可能漏检 | 审计读取全部路由模块,解析页面动态导入,再确认页面通过 `getResource(契约路径)` 使用对应资源且路由具有 `menu.platform.*` 元数据 | `audit-check.test.mjs` 的菜单映射用例 |
| API 或页面可能展示、提交数据库自增 `id` / `*_id` | 对 `src/api``src/views` 全量扫描;详情页的显式过滤逻辑被识别为防护而非泄漏 | `pnpm audit:platform` |
| 仅追加处置和只读状态写入存在审计盲区 | 处置资源必须由 `saf_event` 详情动作触发、不可拥有独立页面;后端仅允许 GET/POST且按事件标识查询处置历史只读资源扫描 API、路由和页面中的 `updateStatus` | 6 个 `audit-check.test.mjs` 用例及逐契约路由方法测试 |
| 创建接口可能回传内部关系 ID、密码散列、地址或其他未枚举字段 | 创建成功统一经过公共身份解析和显式安全白名单,只保留 `identity`、关联 `*_identity`、状态、版本及时间元数据;地址和其他业务字段默认不返回 | `TestCreateGasAccountResolvesGasBasicIdentityBeforePersisting``TestCreatedResourceResponseUsesSafeAllowlist` |
| 轨迹点资源可写,且普通列表/详情可能泄露精确经纬度 | `delivery_track_point` 改为只读契约;仅 JWT 明确声明 `location_scope=precise` 时返回精确坐标,其他响应清空坐标 | `TestListDeliveryTrackPointsMasksCoordinatesWithoutPreciseLocationScope``TestGetDeliveryTrackPointReturnsCoordinatesWithPreciseLocationScope` |
| 通用关键字只影响列表或使用 JSONB、身份及敏感文本字段可能导致总数与结果不一致或扩大数据暴露面 | 仅查询显式允许的安全文本列,并按模型排除个人姓名等敏感列;同一条件同时应用于 count/list | `TestListGasAccountAppliesKeywordToCountAndRows``TestKeywordColumnsUseSafeTextAllowlist` |
| 前端表单缺少持久化类型边界JSONB 字符串可能变成对象,日期不能绑定 Go `time.Time` | JSON 字段在前端校验后保留字符串,后端按模型 GORM 标签将对象/数组规范化为有效 JSON 字符串并拒绝非法文本;日期与时间统一提交 RFC3339 | `TestPrepareResourceValuesNormalizesStringJSONBFields``final-important.test.mjs` 的 JSON 与日期用例、`pnpm type:check` |
| 创建与编辑复用密码必填规则,编辑时可能要求或误提交密码 | 密码仅在创建模式必填并进入请求体;编辑表单隐藏密码字段,载荷边界也强制忽略密码 | `final-important.test.mjs` 的创建/编辑密码语义用例 |
| 空的可选关联标识可能作为空字符串进入请求体 | 载荷边界省略空的可选 `identity` 关系,同时保留必填校验 | `final-important.test.mjs` 的空可选关系用例 |
| 审批只读页缺少同意/驳回入口 | 资源定义声明详情动作,页面按审批身份提交动作及意见并刷新详情和列表 | `final-important.test.mjs` 的审批动作回归用例 |
| 树页面只有新增/编辑,没有符合软删除约束的归档操作 | 增加二次确认,并调用资源归档接口写入 `status=archived`,不执行物理删除 | `final-important.test.mjs` 的树归档回归用例 |
| Biome 依赖 worktree 中不存在的 ignore 文件,模型字段中文注释不完整 | 禁用错误的 VCS ignore 读取;新增 Go AST 测试,要求所有导出模型字段具备中文注释 | `TestEveryModelFieldHasChineseComment``pnpm lint` |
## 身份字段与保留理由
- 对外 HTTP 仅使用 `identity` 及关联的 `*_identity`;数据库主键 `id` 和关系外键 `*_id` 仍用于 GORM 关联、索引和内部查询,并由响应投影剔除,不能删除。
- `status``version``created_at``updated_at` 是归档、乐观并发和审计所需实体元数据,予以保留。
- `product_snapshot``report_metric_snapshot` 保留历史商品及报表快照,避免后续主数据变更影响历史记录。
- 审计的 `before_data``after_data``operator_identity`,以及审批的 `handler_identity``handled_at` 用于追踪处置人和决策,不可作为冗余清除。
## 冗余清理
未删除模型字段或页面。审计没有找到同时满足“不在需求、无后端调用、无前端消费者、无测试或迁移依赖”的候选项;为避免移除潜在兼容入口,保留现有非契约文件,且不将它们纳入菜单与资源契约。
## 验证命令
以下命令在提交前执行:
```powershell
cd backend/api
go test ./...
go build ./cmd/main
cd ../..
node --test frontend/platform_admin/scripts/final-important.test.mjs
cd frontend/platform_admin
pnpm lint
pnpm type:check
pnpm audit:platform
pnpm build
```
| 命令 | 退出码 | 结果 |
| --- | --- | --- |
| `go test ./...` | 0 | 通过 |
| `go build ./cmd/main` | 0 | 通过 |
| `node --test frontend/platform_admin/scripts/final-important.test.mjs` | 0 | 通过6 个终审回归用例;脚本按自身路径定位项目,不依赖当前工作目录 |
| `pnpm lint` | 0 | 通过Biome 检查 169 个文件,无错误,保留 190 个非阻断 warning 和 12 个 info |
| `pnpm type:check` | 0 | 通过 |
| `pnpm audit:platform` | 0 | 通过 |
| `pnpm build` | 0 | 通过 |