Files
hms/wiki/wasm-plugin.md
iven ca50d32f6e
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled
feat(health): 添加 erp-health 健康管理模块骨架
新建 erp-health 原生 Rust crate,覆盖设计规格中定义的 5 大业务域:

- 16 个 SeaORM Entity(患者/家属/标签/医生/健康档案/体征/化验单/预约/排班/随访/咨询等)
- 16 表数据库迁移(含索引、外键、默认值、可回滚)
- 40+ API 路由骨架(患者管理/健康数据/预约排班/随访/咨询/医生管理)
- 12 个权限声明(health.patient/health-data/appointment/follow-up/consultation/doctor 各 .list/.manage)
- DTO / Service / Handler / Event 四层架构,Service 使用 todo!() 占位
- erp-server 集成:模块注册 + AppState FromRef 桥接 + 路由挂载

同步更新 CLAUDE.md 项目进度、wiki 知识库、设计规格文档。
2026-04-23 19:59:22 +08:00

5.2 KiB
Raw Permalink Blame History

title, updated, status, tags
title updated status tags
WASM 插件系统 2026-04-23 stable
wasm
plugin
wasmtime
wit

WASM 插件系统

index 导航。关联: erp-core architecture erp-server

1. 设计决策

为什么选 WASM 而非 Lua / gRPC / dylib

方案 安全性 隔离性 性能 复杂度
WASM 高(沙箱) 进程内隔离 接近原生
Lua 脚本 无隔离
进程外 gRPC 进程级隔离 网络开销
dylib 无隔离 原生

核心权衡WASM 在安全和性能间取得最佳平衡。Wasmtime v43 Component Model 提供类型安全的 Host-Plugin 接口Fuel 防止无限循环。

架构拓扑

┌─────────────────────────────────────────────┐
│  erp-server                                 │
│  ┌───────────┐  ┌────────────────────────┐  │
│  │ EventBus  │  │ PluginRuntime(Wasmtime) │  │
│  │(broadcast)│  │  ┌─────┐  ┌─────┐     │  │
│  └─────┬─────┘  │  │CRM  │  │库存 │     │  │
│        │        │  └──┬──┘  └──┬──┘     │  │
│        │        │  Host Bridge(自动注入  │  │
│        │        │  tenant_id+权限检查)   │  │
│        │        └─────┼──────────────────┘  │
│  ┌─────┴──────┐                            │
│  │ DB(SeaORM) │                            │
│  └────────────┘                            │
└─────────────────────────────────────────────┘

原型验证 (V1-V6)

全部通过WIT+bindgen 编译、Host 调用插件、插件回调 Host API、async 实例化、Fuel 限制、动态加载。

2. 关键文件 + 数据流

核心文件

文件 职责
crates/erp-plugin-prototype/wit/plugin.wit WIT 接口定义Host API + Plugin API
crates/erp-plugin-prototype/src/lib.rs Host 运行时Engine/Store/Linker/HostState
crates/erp-plugin-prototype/tests/test_plugin_integration.rs V1-V6 集成测试

WIT 接口概要

Host 暴露给插件(host-apidb_insert db_query db_update db_delete event_publish config_get log_write current_user check_permission

插件导出给 Hostplugin-apiinit on_tenant_created handle_event

集成契约

方向 模块 接口 触发时机
被调用 ← erp-server PluginEngine 服务启动时恢复插件
调用 → erp-core EventBus 桥接领域事件到插件
提供 → 所有插件 Host API (9 函数) 插件运行时

3. 代码逻辑

插件生命周期

安装(manifest+WASM) → 注册权限 → 实例化(Wasmtime) → init()
  → 日常: db_query/db_insert 通过 data_handler 自动注入 tenant_id + 权限校验
  → 事件: EventBus → handle_event()
  → 升级: upload 新 WASM → 增量 DDL → 卸载旧实例 → 加载新实例

权限系统

权限码由 data_handler.rscompute_permission_code() 自动生成:

{manifest_id}.{url_entity_name}.{action_suffix}
例: erp-crm.customer.list / erp-crm.customer.manage

权限命名铁律: plugin.tomlpermissions[].code 前缀必须与 schema.entities[].name 完全一致,每个实体必须声明 .list + .manage

Host API 数据约定: 所有数据参数用 list<u8> + JSON 序列化Host 自动注入 id/tenant_id/timestamp

同步调用: bindgen 生成的 call_init/call_handle_event 是同步的,只有实例化可以 async

不变量

Fuel 默认 100 万,耗尽时 WASM trapwasm trap: interrupt HasSelf<HostState> 是 Linker 注册的必要类型参数(Data<'a> = &'a mut HostState Core WASM 必须通过 wasm-tools component new 转为 Component 格式才能被 Host 加载

4. 活跃问题 + 陷阱

历史教训

  • CRM 权限码 tag.manage vs 实体 customer_tag → 三个页面 403迁移 m000038 修复)
  • CRM WASM 二进制错误存储了测试插件而非 CRM 插件(重新编译修复)
  • 权限未自动分配给 admin 角色 → 403添加 grant_permissions_to_admin()

注意事项

⚠️ 插件 API 路由用 Path<(Uuid, String)> 解析 plugin_id必须用数据库 UUID 而非 manifest_id ⚠️ 修改 WIT 后需重编译 Host crate 和所有插件

5. 变更记录

日期 变更
2026-04-23 重构为 5 节结构,插件制作流程移至 .claude/skills/plugin-development/
2026-04-19 CRM 权限码修复 (m000038)
2026-04-18 插件权限系统审计

插件制作完整流程: 详见 .claude/skills/plugin-development/SKILL.mdWIT 接口 → 创建 crate → 编译 WASM → 集成测试)