Files
hms/docs/qa/T00-system-integration.md
iven df1d85bfde docs: T40 UI 审计报告 + wiki 更新 + Docker 配置
- T40 UI 审计计划和结果文档(docs/qa/)
- wiki 更新:miniprogram 设计系统合规审计记录 + index 关键数字更新
- 审计 V2 完整报告(docs/audits/v2/)
- 讨论记录文档(docs/discussions/)
- 设计规格和实施计划(docs/superpowers/)
- 角色测试计划和结果(docs/qa/role-test-*)
- Docker 生产部署配置
2026-05-13 23:29:42 +08:00

10 KiB
Raw Blame History

T00 — 系统基础设施与跨切面集成测试

类型: 系统级 | 前置条件: 后端 + 前端服务运行中 | 优先级: P0

本文档覆盖角色测试计划R01-R05未涉及的跨切面关注点。

1. 环境启动验证

# 测试项 操作 预期结果 通过
1.1 后端启动 .\dev.ps1cargo run -p erp-server 服务在 3000 端口启动,日志显示迁移自动执行
1.2 健康检查 curl http://localhost:3000/api/v1/health 返回 200包含各模块状态
1.3 前端启动 cd apps/web && pnpm dev Vite 在 5174 端口启动,浏览器可访问
1.4 OpenAPI 文档 浏览器打开 http://localhost:3000/api/docs/openapi.json 返回完整 OpenAPI JSON
1.5 数据库连接 psql -U postgres -h localhost -d erp -c "\dt" 显示所有表30 基础 + 44 健康 + 3 AI
1.6 Redis 连接 检查后端日志 Redis 连接成功,无超时警告
1.7 Ollama 可达 curl http://127.0.0.1:11434/api/tags 返回模型列表,包含 qwen3:4b

2. 多租户隔离验证

业务背景: HMS 为 SaaS 平台,不同医疗机构(租户)的数据必须完全隔离。

2.1 数据隔离

# 测试项 操作 预期结果 通过
2.1.1 租户 A 查询 以 admin 登录(租户 A→ 查询患者列表 只看到租户 A 的患者
2.1.2 跨租户 API 用租户 A 的 token 直接请求租户 B 的患者 ID 返回 404不是 200+空数据)
2.1.3 租户 ID 注入 检查后端日志中的 SQL 查询 所有 SELECT 都包含 WHERE tenant_id = ?
2.1.4 新增数据隔离 创建患者 → 检查数据库 新记录的 tenant_id 自动注入为当前租户

2.2 权限隔离

# 测试项 操作 预期结果 通过
2.2.1 菜单隔离 不同租户的相同角色登录 菜单列表由 menu_roles 关联决定,可能不同
2.2.2 角色隔离 租户 A 的 doctor 无法访问租户 B 的数据 API 返回空列表或 403

3. 事件总线端到端

业务背景: 模块间通过 EventBus 异步通信事件必须可靠投递Outbox 模式)。

# 测试项 操作 预期结果 通过
3.1 患者创建事件 创建新患者 → 检查 domain_events 出现 patient.created 事件记录
3.2 事件消费 等待 5 秒 → 检查事件状态 事件被消费(状态 processed
3.3 随访完成事件 完成一条随访 → 检查 domain_events 出现 follow_up.completed 或类似事件
3.4 死信队列 检查 dead-letter 存储 无消费失败的事件(或已知原因)
3.5 LISTEN/NOTIFY 创建患者 → 检查 PostgreSQL NOTIFY 日志 通知已发出

4. 权限码全量校验

业务背景: 50 个声明权限码health 39 + ai 6 + dialysis 5前端 AuthButton 覆盖率仅 26%。已知 CRITICAL 问题:health.alert.manage单数vs health.alerts.manage(复数)。

# 测试项 操作 预期结果 通过
4.1 权限码一致性 检查 permissions 表中的 50 个声明码 每个码格式为 模块.实体.操作(如 health.patient.list
4.2 告警权限码修复 登录有告警管理权限的角色 → 打开告警页面 告警管理按钮(确认/处理)正常显示
4.3 AuthButton 覆盖 逐一检查各页面的操作按钮 新增/编辑/删除按钮使用 AuthButton 包裹,权限码匹配
4.4 API 权限守卫 以无权限角色调用受保护 API 返回 403不是 500
4.5 菜单-权限关联 检查 menu_roles 每个角色关联的菜单与测试计划R01-R05一致

5. 冻结模块路由拦截

业务背景: 7 个模块已冻结care_plan、shift 等),路由守卫应拦截访问。

# 测试项 操作 预期结果 通过
5.1 冻结路由拦截 浏览器访问冻结模块路由(如 care_plan 相关路径) 显示"模块已冻结"提示或重定向,不显示空白页
5.2 菜单不可见 检查左侧菜单 冻结模块不显示在菜单中
5.3 API 拦截 调用冻结模块的 API 返回明确错误(如 403 或 410不是 500

6. 并发冲突场景

业务背景: 预约使用 CAS 乐观锁,排班满额时并发预约应被拒绝。

# 测试项 操作 预期结果 通过
6.1 预约并发 同一时段两个请求同时预约 只有一个成功,另一个返回冲突错误
6.2 排班满额 预约数达到排班上限 → 再预约 返回"已满"错误,不超额
6.3 乐观锁冲突 两个请求同时编辑同一条患者 第二个请求返回版本冲突错误
6.4 软删除可见性 删除患者后 → 列表中不显示 列表排除 deleted_at IS NOT NULL 的记录

7. PII 加密全链路

业务背景: 患者敏感信息(姓名、身份证、手机号)使用 AES-256-GCM 加密存储HMAC 盲索引支持搜索。

# 测试项 操作 预期结果 通过
7.1 写入加密 创建患者 → 直接查询数据库 姓名/身份证/手机号字段为密文,非明文
7.2 读取解密 通过 API 查看患者详情 返回明文,可正常显示
7.3 盲索引搜索 按手机号搜索患者 搜索结果正确,命中目标患者
7.4 跨租户加密隔离 租户 A 的加密数据用租户 B 的密钥解密 解密失败或返回乱码,不泄漏明文
7.5 HMAC 索引一致性 创建患者 → 检查 blind_indexes 对应字段有 HMAC 索引记录

8. FHIR API 访问控制

业务背景: 14 个公开 FHIR 路由需验证访问控制。

# 测试项 操作 预期结果 通过
8.1 FHIR 资源访问 GET /api/v1/fhir/Patient 返回 FHIR 格式的患者资源
8.2 无 token 访问 不带 Authorization 头访问 FHIR 端点 公开端点可访问 / 受保护端点返回 401
8.3 越权访问 用普通患者 token 访问其他患者的 FHIR 资源 allowed_patient_ids 限制生效,返回 403
8.4 FHIR 格式验证 检查返回的 JSON 结构 符合 FHIR R4 规范(resourceType 字段存在)

9. SSE / WebSocket 连通性

业务背景: 消息中心使用 SSE 推送未读计数AI 分析使用 SSE 流式返回结果。

# 测试项 操作 预期结果 通过
9.1 SSE 连接 浏览器打开 → 检查 Network 面板 SSE 连接 EventSource 连接到 /api/v1/messages/stream,状态 200
9.2 消息推送 管理员发送消息 → 切换到另一个角色的浏览器 未读计数实时更新SSE 推送)
9.3 SSE 断线重连 断开网络 → 恢复 SSE 自动重连,消息不丢失
9.4 AI SSE 分析 触发 AI 分析(需前端入口或直接 API 调用) SSE 流式返回分析结果

10. 错误恢复场景

# 测试项 操作 预期结果 通过
10.1 Token 过期刷新 登录后等待 token 接近过期(或手动修改 localStorage 前端自动刷新 token无需重新登录
10.2 401 响应处理 后端返回 401 → 检查前端行为 跳转到登录页,不显示空白
10.3 403 响应处理 访问无权限页面 显示 403 提示或重定向,不显示空白
10.4 500 响应处理 触发后端错误(如发送异常数据) 显示友好错误提示,不显示原始堆栈
10.5 Redis 降级 停止 Redis → 发起 API 请求 限流降级为 fail-close503不是无限等待
10.6 数据库连接恢复 短暂断开数据库 → 恢复 连接池自动重建,后续请求正常
10.7 网络中断恢复 断开前端网络 → 恢复 页面恢复数据加载SSE 重连

11. 文件上传

业务背景: 化验单和体检报告支持文件上传。

# 测试项 操作 预期结果 通过
11.1 图片上传 患者详情 → 上传化验单图片 上传成功,图片可预览
11.2 文件大小限制 上传超大文件(>10MB 返回文件大小限制错误
11.3 文件类型限制 上传非允许类型文件(如 .exe 返回文件类型限制错误
11.4 图片预览 点击已上传的图片 全屏预览正常显示

12. 安全边界

基于专家评审安全建议

# 测试项 操作 预期结果 通过
12.1 SQL 注入 在搜索框输入 ' OR 1=1 -- 不返回全量数据,搜索结果为空或正常过滤
12.2 XSS 防护 在患者姓名中输入 <script>alert(1)</script> 存储后显示为转义文本,不执行脚本
12.3 display_name XSS 检查数据库中的 display_name 字段 不包含未转义的 HTMLP1 已知问题)
12.4 CORS 限制 从非白名单 Origin 发起 API 请求 被拒绝(生产环境 CORS 不含通配符)
12.5 JWT 伪造 使用篡改的 JWT 发起请求 返回 401
12.6 批量导出限制 尝试导出大量数据 有分页限制或超时保护

13. 数据完整性

# 测试项 操作 预期结果 通过
13.1 UUID v7 主键 检查任意表的主键格式 为 UUID v7 格式(时间排序)
13.2 审计字段 创建任意记录 → 检查数据库 created_at/updated_at/created_by/updated_by 自动填充
13.3 乐观锁版本 编辑记录两次 → 检查 version 字段 version 递增
13.4 软删除 删除记录 → 直接查询数据库 deleted_at 非空,记录仍存在
13.5 唯一约束 创建重复身份证号的患者 返回唯一约束错误

测试结果

  • 测试人: _________
  • 测试日期: _________
  • 通过数: ___ / 总数: ___
  • 问题记录: