docs: 审计报告(8 份) + 讨论记录(4 份)

审计报告: 基线快照/功能清单/后端完整性/事件系统/参数配置/
差距模式/错误处理/测试覆盖/审计总结报告
讨论记录: 设备管线/端到端测试/三端审计/工作台重构
This commit is contained in:
iven
2026-05-03 19:32:15 +08:00
parent 78c783d332
commit d712ad78c3
13 changed files with 2683 additions and 0 deletions

View File

@@ -0,0 +1,214 @@
# HMS 功能审计 — Phase 3: 事件系统审计
> 日期: 2026-04-30 | 审计范围: 全系统事件总线
## 总览
| 指标 | 值 |
|------|-----|
| 事件类型常量定义 | 25 个event.rs |
| 事件发布调用 | 44 处 |
| 事件消费者 | 14 个11 个 tokio::spawn 任务) |
| 已知未实现事件 | 2 个PATIENT_VERIFIED / PATIENT_DECEASED标记 KNOWN |
---
## 1. 事件发布方清单
### erp-health 模块30 处发布)
| 事件类型 | 发布者 Service | 函数 | Payload 字段 |
|----------|---------------|------|-------------|
| `patient.created` | patient_service.rs | create_patient | patient_id, name, phone |
| `patient.updated` | patient_service.rs | update_patient | patient_id, updated_fields |
| `appointment.created` | appointment_service.rs | create_appointment | appointment_id, patient_id, doctor_id, scheduled_at |
| `appointment.{status}` | appointment_service.rs | update_appointment_status | appointment_id, patient_id, doctor_id, status |
| `appointment.reminder` | appointment_service.rs | send_reminders | appointment_id, patient_id, doctor_id, scheduled_at |
| `follow_up.created` | follow_up_service.rs | create_task | task_id, patient_id, assigned_to |
| `follow_up.batch_created` | follow_up_service.rs | batch_create_tasks | count, task_ids |
| `follow_up.completed` | follow_up_service.rs | batch_complete_tasks | task_ids, completed_count |
| `follow_up.assigned` | follow_up_service.rs | batch_assign_tasks | task_ids, assigned_to |
| `follow_up.overdue` | follow_up_service.rs | check_overdue_tasks | task_id, assigned_to, patient_id |
| `consultation.opened` | consultation_service.rs | create_session | session_id, patient_id, doctor_id |
| `consultation.closed` | consultation_service.rs | close_session | session_id, patient_id, doctor_id |
| `consultation.new_message` | consultation_service.rs | create_message | session_id, sender_id, sender_type |
| `device.readings.synced` | device_reading_service.rs | sync_readings | patient_id, device_type, reading_count |
| `vital_signs.created` | health_data_service.rs | create_vital_signs | patient_id, record_id, indicators |
| `lab_report.uploaded` | health_data_service.rs | create_lab_report | patient_id, report_id, indicator_count |
| `lab_report.reviewed` | health_data_service.rs | review_lab_report | report_id, reviewer_id, status |
| `health_data.critical_alert` | health_data_service.rs | create_vital_signs | patient_id, alert_type, metric_name, metric_value, threshold_value |
| `daily_monitoring.created` | daily_monitoring_service.rs | create_daily_monitoring | patient_id, monitoring_id, record_date |
| `alert.triggered` | alert_engine.rs | evaluate_rules | patient_id, severity, rule_name, alert_id |
| `article.published` | article_service.rs | publish_article | article_id, title, author_id |
| `article.rejected` | article_service.rs | reject_article | article_id, reviewer_id, reason |
| `consent.granted` | consent_service.rs | grant_consent | patient_id, consent_type |
| `consent.revoked` | consent_service.rs | revoke_consent | patient_id, consent_type, reason |
| `points.earned` | points_service.rs | daily_checkin | patient_id, points, balance |
| `points.exchanged` | points_service.rs | exchange_product | patient_id, product_id, order_id, points |
| `points.expired` | points_service.rs | expire_points | count, expired_points_total |
| `doctor.online_status_changed` | doctor_service.rs | update_online_status | doctor_id, old_status, new_status |
### erp-ai 模块2 处发布)
| 事件类型 | 发布者 | 函数 |
|----------|--------|------|
| `ai.analysis.failed` | handler/mod.rs | stream_lab_report 等 |
| `ai.analysis.completed` | handler/mod.rs | stream_lab_report 等 |
### erp-dialysis 模块1 处发布)
| 事件类型 | 发布者 | 函数 |
|----------|--------|------|
| `dialysis.record.created` | dialysis_service.rs | create_record |
### erp-auth 模块1 处发布)
| 事件类型 | 发布者 | 函数 |
|----------|--------|------|
| `user.login` | auth_service.rs | login |
### erp-workflow 模块2+ 处发布)
| 事件类型 | 发布者 | 函数 |
|----------|--------|------|
| `workflow.instance.*` | instance_service.rs | start_instance 等 |
| `workflow.task.timeout` | module.rs | 后台超时检测 |
### erp-plugin 模块3 处发布)
| 事件类型 | 发布者 | 函数 |
|----------|--------|------|
| `plugin.data.*` | data_service.rs | CRUD 操作 |
| `plugin.trigger.*` | data_service.rs | 通知触发 |
| 动态事件 | engine.rs | 插件自定义事件 |
---
## 2. 事件消费方清单
### erp-health 消费者11 个 tokio::spawn 任务)
| # | 消费者名称 | 订阅前缀 | 处理事件 | 业务动作 |
|---|-----------|---------|---------|---------|
| 1 | workflow_task_consumer | `workflow.task.` | `workflow.task.completed` | 更新随访任务状态为 completed |
| 2 | message_consumer | `message.` | `message.sent` | 日志记录(预留扩展) |
| 3 | device_reading_consumer | `device.readings.` | `device.readings.synced` | 触发告警引擎评估 |
| 4 | alert_notifier | `alert.` | `alert.triggered` | 发送应用内告警通知 |
| 5 | patient_welcome | `patient.` | `patient.created` | 发送欢迎消息 |
| 6 | appointment_notifier | `appointment.` | `appointment.confirmed` | 发送预约确认通知 |
| 7 | appointment_cancel_handler | `appointment.` | `appointment.cancelled` | 日志记录(号源释放) |
| 8 | follow_up_escalator | `follow_up.` | `follow_up.overdue` | 发送逾期升级通知 |
| 9 | critical_alert_consumer | `health_data.` | `health_data.critical_alert` | 创建危急值告警记录 |
| 10 | ai_analysis_notifier | `ai.` | `ai.analysis.completed` | 通知关联医生 |
| 11 | dialysis_notifier | `ai.` | `dialysis.record.created` | 日志记录 |
| 12 | consent_notifier | `consent.` | `consent.granted` | 发送授予通知 |
| 13 | consent_revoked_notifier | `consent.` | `consent.revoked` | 发送撤回通知给医护 |
### 其他模块消费者
| 模块 | 消费者 | 订阅范围 |
|------|--------|---------|
| erp-message | SSE handler | 全部事件(转发给前端) |
| erp-plugin | notification handler | `plugin.trigger.` |
| erp-plugin | engine | 按插件 manifest 的 pattern |
---
## 3. 事件常量 vs 发布方 vs 消费方矩阵
| 事件常量 | 事件类型 | 发布方 | 消费方 | 状态 |
|----------|---------|--------|--------|------|
| APPOINTMENT_CREATED | `appointment.created` | ✓ appointment_service | ✓ appointment_notifier前缀匹配 | **ALIVE** |
| ALERT_TRIGGERED | `alert.triggered` | ✓ alert_engine | ✓ alert_notifier | **ALIVE** |
| CONSENT_GRANTED | `consent.granted` | ✓ consent_service | ✓ consent_notifier | **ALIVE** |
| CONSENT_REVOKED | `consent.revoked` | ✓ consent_service | ✓ consent_revoked_notifier | **ALIVE** |
| ARTICLE_PUBLISHED | `article.published` | ✓ article_service | — | **NO CONSUMER** |
| ARTICLE_REJECTED | `article.rejected` | ✓ article_service | — | **NO CONSUMER** |
| CONSULTATION_OPENED | `consultation.opened` | ✓ consultation_service | — | **NO CONSUMER** |
| CONSULTATION_CLOSED | `consultation.closed` | ✓ consultation_service | — | **NO CONSUMER** |
| CONSULTATION_NEW_MESSAGE | `consultation.new_message` | ✓ consultation_service | — | **NO CONSUMER** |
| DEVICE_READINGS_SYNCED | `device.readings.synced` | ✓ device_reading_service | ✓ device_reading_consumer | **ALIVE** |
| DOCTOR_ONLINE_STATUS_CHANGED | `doctor.online_status_changed` | ✓ doctor_service | — | **NO CONSUMER** |
| FOLLOW_UP_CREATED | `follow_up.created` | ✓ follow_up_service | — | **NO CONSUMER** |
| FOLLOW_UP_COMPLETED | `follow_up.completed` | ✓ follow_up_service | — | **NO CONSUMER** |
| FOLLOW_UP_OVERDUE | `follow_up.overdue` | ✓ follow_up_service | ✓ follow_up_escalator | **ALIVE** |
| DAILY_MONITORING_CREATED | `daily_monitoring.created` | ✓ daily_monitoring_service | — | **NO CONSUMER** |
| LAB_REPORT_UPLOADED | `lab_report.uploaded` | ✓ health_data_service | — | **NO CONSUMER** |
| LAB_REPORT_REVIEWED | `lab_report.reviewed` | ✓ health_data_service | — | **NO CONSUMER** |
| HEALTH_DATA_CRITICAL_ALERT | `health_data.critical_alert` | ✓ health_data_service | ✓ critical_alert_consumer | **ALIVE** |
| PATIENT_CREATED | `patient.created` | ✓ patient_service | ✓ patient_welcome | **ALIVE** |
| PATIENT_UPDATED | `patient.updated` | ✓ patient_service | — | **NO CONSUMER** |
| PATIENT_VERIFIED | `patient.verified` | — | — | **KNOWN** 未实现 |
| PATIENT_DECEASED | `patient.deceased` | — | — | **KNOWN** 未实现 |
| POINTS_EXPIRED | `points.expired` | ✓ points_service | — | **NO CONSUMER** |
| POINTS_EARNED | `points.earned` | ✓ points_service | — | **NO CONSUMER** |
| POINTS_EXCHANGED | `points.exchanged` | ✓ points_service | — | **NO CONSUMER** |
---
## 4. 分析结论
### 4.1 活跃事件(有发布+有消费11 个
这是系统核心业务链路,全部正常:
- `workflow.task.completed` → 随访自动完成
- `device.readings.synced` → 告警评估
- `alert.triggered` → 告警通知
- `patient.created` → 欢迎消息
- `appointment.confirmed/cancelled` → 预约通知
- `follow_up.overdue` → 逾期升级
- `health_data.critical_alert` → 危急值告警
- `ai.analysis.completed` → 医生通知
- `dialysis.record.created` → 日志
- `consent.granted/revoked` → 知情同意通知
### 4.2 有发布无消费事件14 个
这些事件被发布到 EventBus 并持久化到 domain_events 表,但没有业务消费者。它们可能仅用于审计追踪或 SSE 前端推送。
**风险评估**
| 事件 | 风险 | 说明 |
|------|------|------|
| `patient.updated` | LOW | 信息性事件,更新操作已直接处理 |
| `vital_signs.created` | LOW | 数据已写入 DB无需后续触发 |
| `lab_report.uploaded` | LOW | 同上 |
| `lab_report.reviewed` | LOW | 同上 |
| `follow_up.created` | LOW | 任务已创建,无需后续触发 |
| `follow_up.completed` | LOW | 状态已更新,无需后续触发 |
| `consultation.*` | LOW | 会话管理已在 service 内直接处理 |
| `article.published/rejected` | LOW | 状态已更新,无需后续触发 |
| `points.earned/exchanged/expired` | LOW | 积分操作已在 service 内完成 |
| `daily_monitoring.created` | LOW | 数据已写入 |
| `doctor.online_status_changed` | LOW | 状态已更新 |
### 4.3 已知未实现事件KNOWN2 个
- `PATIENT_VERIFIED` — 患者认证流程未实现
- `PATIENT_DECEASED` — 死亡记录流程未实现
### 4.4 潜在问题
1. **message.sent 消费者仅为日志记录** — event.rs:119 的消费者仅做 tracing::info实际业务逻辑如更新 consultation last_message_at已在 service 层直接处理,此消费者预留扩展但当前无实质作用。
2. **SSE 全事件转发** — erp-message 的 SSE handler 监听所有事件,意味着所有事件(包括 points.earned 等低优先级事件)都会被推送到前端,可能导致通知噪音。
---
## 5. Payload Schema 一致性验证(抽样 5 个)
| 事件 | 发布方字段 | 消费方解析 | 一致性 |
|------|-----------|-----------|--------|
| `workflow.task.completed` | `task_id` | `task_id` → Uuid | ✅ |
| `device.readings.synced` | `patient_id` | `patient_id` → Uuid | ✅ |
| `health_data.critical_alert` | `patient_id, alert_type, metric_name, metric_value, threshold_value` | 全部解析 | ✅ |
| `follow_up.overdue` | `task_id, assigned_to` | 全部解析 | ✅ |
| `appointment.confirmed` | `doctor_id, patient_id` | 全部解析 | ✅ |
**结论**:所有抽样的关键事件 payload schema 发布方与消费方完全一致。所有消费者都使用幂等检查(`is_event_processed`),防止重复处理。
---
## 6. 事件系统评分
| 检查项 | 评分 | 说明 |
|--------|------|------|
| 事件定义完整性 | 95% | 25/27 常量有发布者2 个 KNOWN 未实现) |
| 消费者覆盖率 | 44% | 11/25 事件有活跃消费者 |
| Payload 一致性 | 100% | 抽样 5 个全部一致 |
| 幂等性保证 | 100% | 所有消费者使用 `is_event_processed` 检查 |
| 死信处理 | 100% | 消费失败自动进入 dead_letter_event 表 |