Files
hms/wiki/erp-core.md
iven ec87ae85cf docs(wiki): 全量 wiki 更新 — C1 晚间血压已修复标记 + 数据校正
- miniprogram.md: 晚间血压 CRITICAL 标记为已修复
- index.md: 症状导航表更新
- architecture/database/erp-core/erp-health/frontend/testing: 同步更新
2026-05-03 19:32:30 +08:00

5.9 KiB
Raw Permalink Blame History

title, updated, status, tags
title updated status tags
erp-core 2026-04-28 stable
core
error
event-bus
module-trait
shared-types

erp-core

index 导航。关联: erp-server database wasm-plugin architecture erp-health

1. 设计决策

erp-core 是 L1 基础层,所有业务模块的唯一共同依赖。定义跨模块共享的契约,不含业务逻辑。

核心决策:

  • AppError 统一错误体系 — 8 种变体映射 HTTP 状态码,? 传播 + Axum IntoResponse 自动转换
  • EventBus 进程内广播 — broadcast channel (1024) + PostgreSQL Outbox + LISTEN/NOTIFY + 幂等消费 + Dead Letter
  • PiiCrypto 加密体系 — AES-256-GCM + KEK/DEK 分层管理 + HMAC 盲索引 + 数据脱敏
  • ErpModule 插件 trait — 统一注册路由和事件处理器 + 拓扑排序启动
  • BaseFields 强制多租户 — 所有实体基础字段模板

2. 关键文件 + 数据流

核心文件

文件 职责
crates/erp-core/src/error.rs AppError 定义、HTTP 映射、From 转换
crates/erp-core/src/events.rs DomainEvent、EventBus、EventHandler trait
crates/erp-core/src/module.rs ErpModule trait、ModuleRegistry
crates/erp-core/src/types.rs BaseFields、Pagination、ApiResponse、TenantContext
crates/erp-core/src/crypto/ PiiCryptoengine/key_manager/masking/hmac_indexAES-256-GCM + KEK/DEK
crates/erp-core/src/sanitize.rs strip_html_tags()、sanitize_string()
crates/erp-core/src/entity/ audit_log, domain_event, processed_event, dead_letter_event
crates/erp-core/src/audit.rs 审计日志记录
crates/erp-core/src/rbac.rs require_permission 权限检查
crates/erp-core/src/lib.rs 模块导出入口

集成契约

方向 模块 接口 触发时机
提供 → erp-auth ErpModule trait, AppError, EventBus 模块实现
提供 → erp-config ErpModule trait, AppError 模块实现
提供 → erp-workflow ErpModule trait, AppError, EventBus 模块实现
提供 → erp-message ErpModule trait, AppError, EventBus 模块实现
提供 → erp-plugin ErpModule trait, AppError, EventBus 模块实现
提供 → erp-health ErpModule trait, AppError, EventBus, sanitize 模块实现
消费 ← erp-server ModuleRegistry 组装 启动时
桥接 ← wasm-plugin EventBus → 插件 handle_event 运行时

3. 代码逻辑

错误处理链

业务 crate (thiserror) → AppError → IntoResponse → HTTP JSON
数据库 (sea_orm::DbErr) → From 转换 → AppError (自动识别 duplicate key → Conflict)

响应格式:{ "error": "not_found", "message": "资源不存在", "details": null }

事件总线

EventBus::publish(DomainEvent)
  → INSERT pending → 内存 broadcast(channel 1024) → UPDATE published → NOTIFY outbox_channel
Outbox Relay: PgListener (LISTEN/NOTIFY) + 30s 兜底轮询 + 自动重连
幂等消费: processed_events 表 + consumer_id
Dead Letter: 失败事件 → dead_letter_events 表

事件字段: id(UUIDv7), event_type("user.created"), tenant_id, payload(JSON), timestamp

命名规则:{模块}.{动作}user.created, workflow.task.completed

健康模块事件:patient.created, appointment.confirmed, appointment.cancelled

模块注册

ErpModule trait → ModuleRegistry::register() →
  build_router(): 折叠所有模块路由 → Axum Router
  register_handlers(): 注册事件处理器 → EventBus

已注册模块AuthModule → ConfigModule → WorkflowModule → MessageModule → PluginModule → HealthModuleAiModule

共享类型

  • TenantContext — 租户上下文tenant_id, user_id, roles, permissions, department_ids
  • Pagination / PaginatedResponse<T> — 分页标准化(每页上限 100
  • ApiResponse<T> — 统一信封 { success, data, message }
  • sanitize_string() — HTML 标签过滤,用于用户输入清理

不变量: erp-core 不依赖任何业务 crate只被依赖 不变量: 所有 API 使用 /api/v1/ 前缀 不变量: tenant_id 从 JWT 中间件注入,应用层不可伪造

4. 活跃问题 + 陷阱

⚠️ crate 内部可用 anyhow,但跨 crate 边界必须转 AppError ⚠️ EventBus 当前为内存 broadcastoutbox 持久化通过后台任务实现 ⚠️ 微信注册路径的 display_name 需调用 sanitize_string() 防止 XSS

2026-04-30 审计发现

事件系统评分

检查项 评分 说明
事件定义完整性 95% 25/27 常量有发布者2 个 KNOWN 未实现)
消费者覆盖率 44% 11/25 事件有活跃消费者
Payload 一致性 100% 抽样 5 个全部一致
幂等性保证 100% 所有消费者使用 is_event_processed 检查
死信处理 100% 消费失败自动进入 dead_letter_event 表

错误处理评分

检查项 评分 说明
错误变体覆盖 95% 8 AppError + 37 领域错误HealthError 26 + AiError 11
Handler 错误传播 100% 统一 ? + IntoResponse无手动 match
PII 错误安全 100% Internal 错误消息对外隐藏
SSE 挂起风险 100% Provider 不可用不会挂起,有完整清理
生产 unwrap() 安全性 95% 2 处中等风险PluginHost::db + 信号量 acquire

审计日志140 处调用 / 33 文件 / SHA256 哈希链 / 变更快照

运行时日志缺口health service 层仅 11 处 tracing26 个文件),运维排查困难

5. 变更记录

日期 变更
2026-05-01 审计结果更新:事件系统 44% 消费者覆盖率 / 错误处理 95% / 审计日志 140 处 / 运行时日志不足
2026-04-25 添加 erp-health 集成契约、健康模块事件、sanitize 模块引用
2026-04-23 重构为 5 节结构,更新为已完全集成状态