Files
erp/docs/discussions/2026-04-18-plugin-platform-brainstorm.md
iven 841766b168
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
fix(用户管理): 修复用户列表页面加载失败问题
修复用户列表页面加载失败导致测试超时的问题,确保页面元素正确渲染
2026-04-19 08:46:28 +08:00

616 lines
23 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.

# ERP 平台发散式探讨记录
> 日期: 2026-04-18 | 形式: 无主题发散式互动讨论
---
## 项目当前状态快照
**已完成:**
- Phase 1-6 核心平台 (core/auth/config/workflow/message/plugin)
- WASM 插件系统 (Wasmtime + WIT + 动态表 + 热更新)
- 2 个行业插件 (CRM 5实体 + 进销存 6实体)
- Q2-Q4 成熟度路线图 (安全/架构/测试/插件生态)
- 13 个 Rust crate, 37 个迁移, 15+ 前端页面
**进行中 (29 个未提交文件):**
- P0 平台能力升级 (实体关系增强/字段校验/前端去硬编码)
- 插件系统增强 (混合执行模型/聚合查询扩展/热更新原子回滚/Schema演进)
**代码中的 TODO:**
- Workflow 超时自动完成/升级逻辑
- Redis 缓存层 (data_service)
---
## 发散探讨方向
### 方向 A: 技术纵深 — 平台能力的下一个突破点
**插件系统能力边界在哪里?**
- 混合执行模型 (WASM + Host Query) 的安全边界如何界定?
- 插件能否拥有自己的定时任务?事件订阅后的异步处理链?
- WASM 组件之间的通信机制 — 插件 A 能否调用插件 B 的能力?
- 插件市场/分发机制 — 如何做到"一键安装"
**性能与规模化的隐藏挑战:**
- 动态表在海量数据下的查询性能 — 索引策略?
- 多租户隔离在大规模场景下的瓶颈 — schema-per-tenant 何时比 row-level 更优?
- WASM 执行的 Fuel 限制如何平衡安全与灵活性?
- 热更新期间的请求如何处理 — 连接排空?
### 方向 B: 业务纵深 — ERP 领域的深度探索
**CRM 插件的完整度缺口:**
- 商机/销售漏斗 — 从线索到成单的全链路
- 合同管理 — 模板、电子签章、履约跟踪
- 报价单 — 产品目录、价格策略、审批流
- 客户画像 — 标签体系、行为追踪、智能推荐
**下一个行业插件应该是什么?**
- 财务 (总账/应收/应付/固定资产)
- 采购 (供应商/询价/采购订单/入库)
- 制造 (BOM/工单/排产/质检)
- 人力 (员工/考勤/薪资/绩效)
- 电商 (商品/订单/物流/售后)
**跨模块业务流程:**
- 从销售订单 → 采购 → 入库 → 付款 的端到端流程
- 插件间的数据如何流转?订单确认触发采购申请?
- 工作流引擎如何编排跨插件流程?
### 方向 C: 体验纵深 — 前端与用户交互
**低代码/零代码的可能性:**
- 插件的前端页面能否完全由 schema 驱动生成?
- 可视化表单设计器 — 拖拽生成插件页面
- 自定义 Dashboard — 用户拼装自己的工作台
- 报表引擎 — 从数据到图表的可视化配置
**移动端/多端体验:**
- PWA 方案 — 离线能力 + 推送通知
- Tauri 桌面端何时启动?哪些场景需要桌面端?
- 小程序/企业微信集成 — 中国市场的刚需?
**AI 增强交互:**
- 自然语言查询 — "帮我查上个月销售额最高的 10 个客户"
- 智能推荐 — 基于操作习惯的快捷入口
- 数据洞察 — 自动发现异常趋势并提醒
- AI 辅助填单 — 自动补全/智能校验
### 方向 D: 商业纵深 — SaaS 化与商业化
**多租户高级能力:**
- 租户级别的功能开关 — 不同套餐解锁不同插件
- 计量计费 — 按用户数/存储/API调用量计费
- 租户数据导出/迁移 — 保障数据主权
- 白标/品牌定制 — 租户自定义 Logo/主题
**开放平台战略:**
- API Gateway + 开发者门户
- Webhook 系统 — 外部系统集成
- 第三方插件审核/上架流程
- 合作伙伴生态 — ISV 开发行业插件
### 方向 E: 团队与工程效率
**开发体验提升:**
- 插件开发脚手架 CLI — `erp-plugin create crm`
- 本地开发热重载 — 改 WASM 代码即时生效
- 插件调试工具 — 断点/日志/性能分析
- 一键生成插件 CRUD — 从 schema 到完整页面
**DevOps 与运维:**
- 蓝绿部署 / 金丝雀发布策略
- 数据库迁移的零停机方案
- 多环境管理 (dev/staging/prod)
- 监控告警体系 (APM + 日志聚合)
---
## 讨论记录
> 以下是互动讨论的要点,按时间顺序记录
### Round 1: "造一个财务插件来验证平台" — 立刻暴露了跨插件数据引用的缺失
**用户意图:** 希望通过搭建第二个行业插件(财务/应收),验证基座和插件系统,特别是与 CRM 插件的数据交互。
**已发现的系统缺陷 — 跨插件数据引用完全不支持:**
| 能力 | 现状 | 影响 |
|------|------|------|
| `ref_entity` 跨插件引用 | 仅限当前插件表空间 | 财务插件的 `customer_id` 无法声明指向 CRM 的 customer |
| Host API 跨插件查询 | `db-query` 无 plugin_id 参数 | WASM 插件无法查询其他插件数据 |
| PluginRelation 跨插件 | `entity` 字段无插件限定 | 无法声明跨插件的关联关系 |
| 前端 entity_select | 仅加载当前插件数据源 | 下拉框无法显示其他插件的实体列表 |
| 引用完整性校验 | 仅校验当前插件表空间 | 跨插件的外键约束无法生效 |
**进销存插件已有的"绕路":** `customer_id` 作为裸 UUID 存在,没有 `ref_entity` 声明 — 证明这是一个已知的痛点。
**唯一现有机制:** EventBus 事件广播(松耦合通知),但无法支持同步查询或声明式引用。
**财务插件与 CRM 的理想交互场景:**
```
CRM.customer ──引用──→ Finance.invoice.customer_id (外键 + 下拉选择)
CRM.opportunity ──引用──→ Finance.sales_order.opportunity_id
CRM.contact ──引用──→ Finance.quote.contact_id
```
**要实现这些,需要改造:**
1. `manifest.rs` — PluginField/PluginRelation 增加 `ref_plugin` 字段
2. `data_service.rs` — validate_ref_entities 支持跨插件表名解析
3. `plugin.wit` + `host.rs` — 新增跨插件查询 API
4. `dynamic_table.rs` — 表名解析支持目标 plugin_id
5. 前端 entity_select — 支持加载其他插件数据源
6. 权限模型 — 跨插件数据访问控制
### Round 2: 方案收敛 — 软引用 + 实体注册表 + 优雅降级
**决策记录:**
| 问题 | 决策 | 理由 |
|------|------|------|
| 引用模式 | **声明式** (plugin.toml) | 与现有 schema-driven 模式一致,插件作者零代码 |
| 依赖严格度 | **完全独立,无硬依赖** | SaaS 用户必须能自由组合/卸载插件 |
| 实体归属 | **插件自拥有,平台注册表发现** | 不改变现有模型,通过注册表实现运行时发现 |
| 悬空引用 | **软警告 + 后台对账** | 永不阻塞用户操作,对账工具引导修复 |
**架构设计:**
```
┌────────────────────────────────────────────────┐
│ Layer 3: Plugin (财务/采购/制造...) │
│ - optional_dependencies 声明 │
│ - ref_scope = "external" 跨插件引用字段 │
├────────────────────────────────────────────────┤
│ Layer 2: Entity Registry (平台实体注册表) │
│ - 插件安装时注册实体、卸载时标记 inactive │
│ - 查询时动态发现源插件 │
│ - 悬空引用检测 + 对账报告 │
├────────────────────────────────────────────────┤
│ Layer 1: Plugin System (现有基础设施) │
│ - 动态表、Host API、EventBus 不变 │
│ - 新增 Entity Registry 接入点 │
└────────────────────────────────────────────────┘
```
**plugin.toml 声明示例:**
```toml
[dependencies.crm]
optional = true
description = "客户管理 — 自动关联客户数据"
[[schema.entities.fields]]
name = "customer_id"
field_type = "uuid"
ref_entity = "customer"
ref_scope = "external"
ref_display_field = "name"
ref_fallback_label = "外部客户"
```
**运行时行为:**
| 源插件状态 | 写入 | 读取 | 展示 |
|-----------|------|------|------|
| 已安装 | 强校验 | JOIN 富化 | ✅ 绿色链接 "张三" |
| 未安装 | 无校验 | 原始 UUID | ⬜ 灰色 "外部客户" |
| 刚重新启用 | 新写入强校验 | 后台对账 | ⚠️ 黄色警告 (悬空) |
**悬空引用处理 (CRM 重新启用时):**
1. 后台扫描所有 `ref_scope=external` 的字段
2. 生成引用对账报告(有效/悬空分类)
3. 前端提示用户逐条处理(映射/清空/忽略)
4. 永不硬阻塞用户操作
**需改造的 6 个点:**
1. `manifest.rs` — 新增 `ref_scope`, `ref_display_field`, `ref_fallback_label`, `dependencies`
2. `entity_registry` (新模块) — 实体注册/发现/inactive 标记
3. `data_service.rs` — validate_ref_entities 支持运行时发现
4. `host.rs` + `plugin.wit` — 新增 resolve-ref-entity API
5. 前端 `entity_select` — 检测注册表,有源插件加载下拉,无则降级
6. 对账工具 — 后台扫描 + 前端对账 UI
### Round 3: 插件生态与商业化 — 技术优先路径
**用户选择:** 技术优先 → 市场,先做好平台能力再考虑商业模式。
**发现的三大技术缺口:**
1. **插件质量保障** — 安全扫描、性能基准、兼容性检测、运行时监控全部缺失
2. **插件配置与数据管理** — 导入导出、打印模板、配置 UI、自定义视图全部缺失
3. **插件市场/商店** — 浏览、发现、一键安装、评分全部缺失
**决策: 这些能力应该是平台级通用服务,不是插件各自实现。**
新增架构层:
```
插件 → Plugin Platform Services → Plugin System → ERP Core
导入导出 / 打印 / 配置 / 视图 / 通知 / 编号
```
**平台 P1 通用服务清单:**
| 服务 | 接入方式 | 财务插件示例 |
|------|---------|-------------|
| 数据导入导出 | plugin.toml 声明 importable/exportable | 导入客户清单、导出发票明细 |
| 打印模板 | 模板文件 + schema 映射 | 发票 PDF、收款凭证 |
| 插件配置 UI | plugin.toml 声明 settings | 税率表、付款条件、发票前缀 |
| 自定义视图 | 用户保存列/筛选配置 | 财务看不同列、销售看不同列 |
| 通知规则 | 插件定义触发事件 | 发票逾期 → 通知负责人 |
| 编号规则 | 复用 erp-config 的编号服务 | INV-2026-0001 |
### Round 4: 收敛 — 全部整合为一份设计规格
用户确认将所有讨论成果写入一份"插件平台演进设计规格"文档。
---
## 设计规格: ERP 插件平台演进路线图
> 基于 2026-04-18 发散式探讨的成果,涵盖跨插件引用、平台通用服务、质量保障、插件市场四个维度。
### 1. 背景与动机
ERP 平台已完成 Phase 1-6 核心开发和 Q2-Q4 成熟度路线图。当前有两个行业插件CRM + 进销存)运行在 WASM 插件系统上。但通过分析发现:
- **跨插件数据引用完全不支持** — 进销存的 `customer_id` 只能存裸 UUID
- **插件无通用业务能力** — 导入导出/打印/配置/视图每个插件都要自己实现
- **无质量保障机制** — 第三方插件的安全性和性能无法保证
- **无发现和分发渠道** — 用户无法自助发现和安装插件
目标:通过搭建财务/应收插件来验证和推动这些平台能力的实现。
### 2. 跨插件数据引用系统
#### 2.1 设计原则
- **插件完全独立** — 任何插件可独立安装/卸载,不受其他插件影响
- **声明式配置** — 跨插件引用通过 plugin.toml 声明,插件作者零代码
- **优雅降级** — 源插件不存在时功能降级,不阻塞用户操作
- **软警告** — 外部引用问题永远是警告,不是错误
#### 2.2 实体注册表 (Entity Registry)
**数据结构:**
```
entity_registry:
- entity_name: string # 实体名 (如 "customer")
- plugin_id: string # 注册该实体的插件 ID
- display_fields: string[] # 用于下拉显示的字段列表
- search_fields: string[] # 用于搜索的字段列表
- status: active | inactive # 插件卸载时标记 inactive
- registered_at: timestamp
- tenant_id: uuid # 多租户隔离
```
**生命周期:**
- 插件安装 → 注册所有 entities 到 registry
- 插件启用 → status = active
- 插件禁用 → status = inactive数据保留
- 插件卸载 → status = inactive + 标记为 orphaned
#### 2.3 plugin.toml 扩展
```toml
# 可选依赖声明
[dependencies.crm]
optional = true
description = "客户管理 — 自动关联客户数据,未安装时客户字段为手动输入"
[dependencies.inventory]
optional = true
description = "进销存 — 自动关联商品数据"
# 跨插件引用字段
[[schema.entities.fields]]
name = "customer_id"
field_type = "uuid"
display_name = "客户"
ref_entity = "customer" # 目标实体名
ref_scope = "external" # "internal" (默认) | "external"
ref_display_field = "name" # 下拉框显示字段
ref_search_fields = ["name", "phone"] # 搜索字段
ref_fallback_label = "外部客户" # 降级时显示文本
```
#### 2.4 运行时行为
**写入时校验:**
```
IF ref_scope == "external":
registry = EntityRegistry.find("customer")
IF registry.status == "active":
强校验: customer_id 必须存在于 registry.plugin_id 的对应表中
ELSE:
无校验: 接受任意 UUID
```
**读取时富化:**
```
IF ref_scope == "external" AND registry.status == "active":
JOIN plugin_{registry.plugin_id}_{ref_entity} 获取 display_field
前端显示: "张三 (CRM)" (绿色可点击链接)
ELIF ref_scope == "external" AND registry.status == "inactive":
前端显示: "外部客户 ({uuid})" (灰色)
```
**悬空引用处理:**
```
ON plugin.activate:
1. 后台扫描所有 ref_scope="external" 且指向本插件实体的字段
2. 验证每个 UUID 是否存在于本插件表中
3. 生成对账报告: { valid: N, dangling: M, details: [...] }
4. 前端展示对账结果,用户逐条处理
```
#### 2.5 需要改造的文件
| 文件 | 改动 | 复杂度 |
|------|------|--------|
| `crates/erp-plugin/src/manifest.rs` | 新增 `ref_scope`, `ref_display_field`, `ref_search_fields`, `ref_fallback_label`; 新增 `DependenciesSection` | 低 |
| `crates/erp-plugin/src/entity_registry.rs` (新) | 实体注册/发现/inactive 标记/对账 | 中 |
| `crates/erp-plugin/src/data_service.rs` | `validate_ref_entities` 支持运行时发现外部引用 | 中 |
| `crates/erp-plugin/src/host.rs` | 新增 `resolve_ref_entity` Host API | 中 |
| `crates/erp-plugin/wit/plugin.wit` | 新增 `resolve-ref-entity` 接口 | 低 |
| `crates/erp-plugin/src/service.rs` | 插件安装/卸载时维护 Entity Registry | 中 |
| `apps/web/src/` 前端 | entity_select 组件支持跨插件数据源 + 降级显示 + 对账 UI | 高 |
### 3. 插件平台通用服务层 (P1)
#### 3.1 数据导入导出服务
**设计思路:** 插件在 plugin.toml 中声明哪些实体支持导入导出,平台提供统一的导入导出 UI 和引擎。
```toml
# plugin.toml 中的声明
[[schema.entities]]
name = "invoice"
display_name = "发票"
importable = true
exportable = true
import_template = "invoice_import_template.xlsx" # 可选: 自定义导入模板
[[schema.entities]]
name = "payment"
display_name = "收款"
importable = true
exportable = true
```
**平台能力:**
- 自动生成导入模板(基于 schema entities fields
- Excel/CSV 解析 + schema 字段校验
- 批量写入(支持事务 + 错误行级报告)
- 导出为 Excel/CSV支持筛选条件
- 导入历史记录 + 回滚
**实现位置:** 新增 `crates/erp-plugin/src/import_export.rs`,前端新增 `ImportExportModal` 通用组件。
#### 3.2 打印模板引擎
**设计思路:** 平台提供 HTML → PDF 的模板渲染能力,插件定义模板和字段映射。
```toml
# plugin.toml 中的声明
[[templates]]
name = "invoice_pdf"
display_name = "发票"
entity = "invoice"
format = "pdf"
template_file = "templates/invoice.html" # HTML 模板
```
**平台能力:**
- HTML 模板渲染 → PDF 下载
- 模板变量替换(基于实体字段)
- 租户级模板自定义(覆盖默认模板)
- 打印预览
**实现位置:** 后端使用 `wkhtmltopdf``headless-chrome` 渲染,前端新增 `PrintPreviewModal` 组件。
#### 3.3 插件配置 UI
**设计思路:** 插件在 plugin.toml 中声明配置项,平台自动生成配置页面。
```toml
# plugin.toml 中的声明
[settings]
[[settings.fields]]
name = "default_tax_rate"
display_name = "默认税率"
field_type = "number"
default_value = 0.13
[[settings.fields]]
name = "invoice_prefix"
display_name = "发票前缀"
field_type = "text"
default_value = "INV"
[[settings.fields]]
name = "payment_terms"
display_name = "默认付款条件"
field_type = "select"
options = ["net_15", "net_30", "net_60", "cod"]
default_value = "net_30"
```
**平台能力:**
- 根据 settings 声明自动生成配置表单
- 配置数据存储在 `plugin_settings`tenant_id + plugin_id + key/value
- 配置变更时通知插件(通过事件)
- 支持配置权限控制(仅管理员可改)
#### 3.4 自定义视图
**设计思路:** 用户可以保存列表页的列配置和筛选条件。
```
user_views:
- id: uuid
- user_id: uuid
- plugin_id: string
- entity_name: string
- view_name: string
- columns: string[] # 显示的列
- filters: json # 筛选条件
- sort: json # 排序条件
- is_default: boolean
```
**平台能力:**
- 列表页支持列拖拽排序、显示/隐藏
- 筛选条件保存/加载
- 每个用户可以有多个视图
- 支持共享视图给同角色用户
#### 3.5 通知规则
**设计思路:** 插件在 plugin.toml 中声明可触发的事件,平台提供通知规则配置 UI。
```toml
# plugin.toml 中的声明
[[trigger_events]]
name = "invoice.overdue"
display_name = "发票逾期"
description = "发票超过付款期限未收款"
[[trigger_events]]
name = "payment.received"
display_name = "收款确认"
```
**平台能力:**
- 规则引擎: WHEN event THEN notify [user/role/department]
- 复用 erp-message 的通知渠道
- 租户级规则配置
- 通知模板自定义
#### 3.6 编号规则 (已有基础扩展)
**设计思路:** 复用 erp-config 的编号规则服务,扩展为插件可接入。
```toml
# plugin.toml 中的声明
[[numbering]]
entity = "invoice"
prefix = "INV"
format = "{PREFIX}-{YEAR}-{SEQ:4}"
reset_rule = "yearly" # daily/monthly/yearly/never
```
### 4. 插件质量保障
#### 4.1 上传时校验
```
插件上传 → Schema 校验 → WASM 二进制验证 → 安全扫描 → 性能基准 → 发布/拒绝
```
| 阶段 | 校验内容 | 现状 |
|------|---------|------|
| Schema 校验 | plugin.toml 格式、字段类型、权限码一致性 | ✅ 已有部分 |
| WASM 验证 | 二进制格式、WIT 兼容性、导出函数检查 | ✅ 已有 |
| 安全扫描 | 动态表 SQL 注入风险、Fuel 耗尽、内存泄漏 | ❌ 缺失 |
| 性能基准 | 标准 CRUD 操作在 N 条数据下的响应时间 | ❌ 缺失 |
| 兼容性 | 平台版本匹配、依赖插件版本兼容 | ❌ 缺失 |
#### 4.2 运行时监控
```
plugin_runtime_metrics:
- plugin_id: string
- error_rate: float # 24h 错误率
- avg_response_ms: float # 平均响应时间
- fuel_consumption: float # 平均 Fuel 消耗
- memory_peak_mb: float # 内存峰值
- active_instances: int # 活跃实例数
```
**告警规则:**
- 错误率 > 5% → 警告
- 平均响应 > 2s → 警告
- Fuel 消耗异常 → 警告
- 内存持续增长 → 疑似泄漏
### 5. 插件市场/商店
#### 5.1 功能范围
| 功能 | 说明 |
|------|------|
| 插件目录 | 按行业/功能分类浏览 |
| 搜索 | 按名称/标签/行业搜索 |
| 详情页 | 截图、演示、功能描述、权限说明 |
| 一键安装 | 上传 → 自动安装 → 配置 → 启用 |
| 评分/评论 | 用户评分和使用反馈 |
| 版本管理 | 版本列表、更新日志、回滚 |
| 依赖提示 | 安装时提示可选依赖("推荐配合 CRM 使用" |
#### 5.2 技术实现
- 后端: 新增 `plugin_store` 表 + API
- 前端: 新增 `PluginStore` 页面
- 管理端: 管理员审核/上架/下架
### 6. 验证计划 — 财务/应收插件
#### 6.1 实体设计
| 实体 | 字段概要 | 跨插件引用 |
|------|---------|-----------|
| invoice (发票) | 编号/客户/金额/税额/状态/到期日 | customer_id → CRM.customer |
| invoice_line (发票行) | 发票/商品/数量/单价/税额 | product_id → Inventory.product |
| payment (收款) | 发票/金额/方式/日期/状态 | invoice_id → 本插件内部 |
| quote (报价单) | 编号/客户/有效期/状态 | customer_id → CRM.customer |
| quote_line (报价行) | 报价单/商品/数量/单价 | product_id → Inventory.product |
#### 6.2 验证矩阵
| 能力 | 验证方式 | 预期结果 |
|------|---------|---------|
| 跨插件引用 (CRM 安装) | 创建发票时选择客户 | entity_select 下拉显示 CRM 客户列表 |
| 跨插件引用 (CRM 卸载) | 创建发票时输入客户 | 降级为文本输入,不阻塞 |
| 悬空引用对账 | CRM 卸载→创建发票→重新安装 CRM | 对账报告显示悬空引用,用户可修复 |
| 数据导入 | 导入 Excel 客户清单 | 解析+校验+批量写入 |
| 数据导出 | 导出发票列表为 Excel | 筛选+下载 |
| 打印模板 | 打印发票 PDF | HTML→PDF 渲染 |
| 插件配置 | 设置税率/发票前缀 | 自动生成的配置页面 |
| 编号规则 | 创建发票自动编号 | INV-2026-0001 |
| 通知规则 | 发票逾期通知 | 规则引擎触发通知 |
| 独立安装 | 不安装 CRM 单独安装财务 | 所有功能正常,客户字段降级 |
### 7. 实施优先级
```
P0 (已完成/进行中): P0 平台能力升级 (实体关系增强/字段校验/前端去硬编码)
插件系统增强 (混合执行模型/聚合查询/热更新回滚/Schema演进)
P1 (跨插件引用): Entity Registry + ref_scope 扩展 + 前端 entity_select 改造
这是所有后续能力的基础
P2 (平台通用服务): 数据导入导出 → 插件配置 UI → 编号规则扩展 → 通知规则
按业务迫切程度排序
P3 (质量保障): 上传时安全扫描 → 性能基准 → 运行时监控
逐步建立信任体系
P4 (插件市场): 插件目录 → 一键安装 → 版本管理 → 评分评论
商业化的最后一块拼图
验证: 财务/应收插件贯穿 P1-P2每完成一个 P 就用财务插件验证
```
### 8. 风险与缓解
| 风险 | 影响 | 缓解措施 |
|------|------|---------|
| Entity Registry 查询性能 | 每次数据操作都要查注册表 | 内存缓存 + DashMap注册表数据量极小 |
| 悬空引用数据量过大 | 对账扫描耗时长 | 异步后台任务 + 分批处理 + 进度条 |
| Excel 导入内存占用 | 大文件解析 OOM | 流式解析 + 批量提交 + 文件大小限制 |
| 打印模板安全 | 模板注入攻击 | 沙箱渲染 + 变量白名单 |
| 插件市场审核成本 | 人工审核效率低 | 自动化扫描 + 人工抽查 + 社区举报 |