Files
hms/wiki/erp-core.md
iven 75cd305996
Some checks failed
CI / security-audit (push) Has been cancelled
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
docs(wiki): 全景梳理 — 更新 9 个 wiki + CLAUDE.md scope + 头脑风暴记录
基于 3 个并行探索代理的全面扫描结果,更新 wiki 数据至实际状态:
- index.md: 18 crate / 76 迁移 / 44 实体 / 77k 行 / 409 提交
- erp-health.md: 44 实体 / 21 handler / 22 权限 / 25 事件 / 6 消费者
- erp-server.md: 9 后台任务 / RLS 中间件栈
- architecture.md: 新增 erp-ai/dialysis 到依赖图 / 测试覆盖表
- testing.md: 225 单元 + 159 集成 / 4 模块零测试警告
- database.md: 76 迁移 / RLS+哈希链+盲索引+Dead Letter
- erp-core.md: PiiCrypto 加密体系 / EventBus 完整描述
- frontend.md: 163 文件 / 5 store / 10 API 文件
- CLAUDE.md: 新增 health/ai/dialysis/assessment scope

头脑风暴 4 个议题决策:
- dialysis: 接入激活
- 测试: 按风险排序(workflow > ai > message > config)
- AI: 数据桥接优先
- 路线图: AI 驱动 3 个月 5 Phase
2026-04-28 14:53:04 +08:00

113 lines
4.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.
---
title: erp-core
updated: 2026-04-28
status: stable
tags: [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 → **HealthModule****AiModule**
### 共享类型
- `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
## 5. 变更记录
| 日期 | 变更 |
|------|------|
| 2026-04-25 | 添加 erp-health 集成契约、健康模块事件、sanitize 模块引用 |
| 2026-04-23 | 重构为 5 节结构,更新为已完全集成状态 |