diff --git a/docs/MDTODO/details/pikaoa-enterprise-platform/R1.1_Task_Report.md b/docs/MDTODO/details/pikaoa-enterprise-platform/R1.1_Task_Report.md new file mode 100644 index 00000000..d4cc6e99 --- /dev/null +++ b/docs/MDTODO/details/pikaoa-enterprise-platform/R1.1_Task_Report.md @@ -0,0 +1,508 @@ +# PikaOA R1.1 开源办公系统与组件调研报告 + +## 1. 任务信息 + +| 字段 | 内容 | +| --- | --- | +| MDTODO | [R1.1](../../pikaoa-enterprise-platform.md) | +| 执行 issue | [pikasTech/unidesk#1953](https://github.com/pikasTech/unidesk/issues/1953) | +| 上层规格 | [PJ2026-03](../../../../project-management/PJ2026-03/specs/PJ2026-03-pikaoa.md) | +| 调研日期 | 2026-07-13 | +| 交付性质 | 隔离选型文档,不包含业务代码、运行面、Secret 或 CI/CD 变更 | + +本报告只为 PikaOA 后续实现提供证据和建议,不改变 PJ2026-03 已冻结的模块化单体、CLI-first、 +HWLAB v0.3 同族前端和 YAML-first 方向。 + +## 2. 决策摘要 + +### 2.1 总体结论 + +- 不直接采用 ERPNext、Odoo、Twenty、EspoCRM、Dolibarr 或 OpenProject 作为 PikaOA 底座: + - 这些系统的领域边界、扩展模型、技术栈和升级路径会反向约束 PJ2026-03; + - 多数完整系统使用 GPL 或 AGPL,闭源可能性未知时不应复制源码或形成紧耦合派生实现; + - PikaOA 首期需要的是稳定平台内核与合同、发票事实,而不是迁移完整 ERP/CRM 产品。 +- 直接采用宽松许可证的 Go、Vue 和可观测性基础组件: + - HTTP:`chi`; + - PostgreSQL:`pgx` 与 `sqlc`; + - 数据库迁移:`goose`; + - CLI:`Cobra`; + - 授权:首期 `Casbin`,保留以后提取到 `OpenFGA` 的边界; + - 事务消息:PostgreSQL outbox 与 `Watermill`; + - 前端:Vue 3、Vite、TypeScript、Vue Router、Pinia、Tailwind; + - 可观测性:OpenTelemetry Go、OTLP Collector、Prometheus Go client 和结构化日志关联。 +- 仅参考成熟系统的业务建模,不复制实现: + - ERPNext/Frappe 的单据提交、取消、修订和审计思路; + - Odoo 的发票冲销、贷项通知单与会计事实保留思路; + - CRM 的统一伙伴、联系人、标签与上下文角色模型; + - Paperless-ngx 的文档归档、检索、标签和权限思路; + - Documenso 的签署流程与签署证据思路。 +- 首期不采用 `OpenFGA`、`Asynq`、`Atlas`: + - `OpenFGA` 增加独立服务和授权模型运维成本,当前 RBAC 可由 `Casbin` 满足; + - `Asynq` 依赖 Redis,首期已有 PostgreSQL outbox 即可提供可审计异步处理; + - `Atlas` 与 `goose` 职责重叠,首期应保持单一迁移真相。 + +### 2.2 推荐分类 + +- 直接采用: + - `chi`、`pgx`、`sqlc`、`goose`、`Cobra`、`Casbin` 和 `Watermill`; + - Vue 3、Vue Router、Pinia 和 Tailwind; + - OpenTelemetry Go、Prometheus Go client 和 OTLP Collector。 +- 组件复用: + - HWLAB v0.3 的前端布局语言、路由守卫和 API 错误呈现; + - HWLAB v0.3 的响应式工作台模式; + - 现有 UniDesk OTel、Tempo 和 Prometheus 运行能力。 +- 仅参考: + - ERPNext/Frappe、Odoo、Twenty、EspoCRM 和 Dolibarr; + - OpenProject、Documenso 和 Paperless-ngx; + - OpenFGA 和 Asynq。 +- 不采用: + - 完整 OA、ERP 或 CRM 产品作为 PikaOA 底座; + - GPL 或 AGPL 源码复制; + - 首期微服务拆分; + - 同时使用多套 HTTP、迁移或异步任务框架。 + +## 3. 调研方法与活跃度口径 + +- 来源优先级: + - 项目官方 GitHub 仓库及其许可证文件; + - 项目官方文档; + - GitHub Releases 和仓库最近推送时间。 +- 活跃度判定: + - `高`:调研日附近仍有提交,并在近数月内发布版本; + - `中`:持续维护,但发布节奏较慢或主要以稳定维护为主; + - 活跃度只说明维护状态,不等于适合 PikaOA。 +- 表中版本和活跃度是 2026-07-13 的采样证据: + - 最终依赖版本必须由实现任务根据锁文件、安全公告和兼容性验证选择; + - 不把本报告中的版本固化为部署策略。 + +## 4. 完整办公、ERP、CRM 与文档系统 + +### 4.1 ERPNext 与 Frappe + +- 来源: + - [ERPNext](https://github.com/frappe/erpnext); + - [Frappe](https://github.com/frappe/frappe)。 +- 活跃度与技术栈: + - 高;Python、JavaScript 和元数据驱动框架; + - ERPNext 于调研日仍有发布。 +- 许可证: + - ERPNext 为 GPL-3.0; + - Frappe 框架和附属组件需按锁定版本逐项复核。 +- 可复用层次: + - 单据状态、提交后修改限制、取消与修订; + - 审计时间线和模块元数据思路。 +- 成本与风险: + - 领域和框架绑定深; + - 采用整套系统会替换 Go 与既定模块边界; + - GPL 代码复制风险高。 +- 结论:仅参考业务语义,不采用产品或源码。 + +### 4.2 Odoo + +- 来源:[Odoo](https://github.com/odoo/odoo)。 +- 活跃度与技术栈:高;Python、JavaScript 和模块化 ERP。 +- 许可证: + - Community 核心通常为 LGPL-3.0; + - Enterprise 和单独模块另有许可,必须逐项核验。 +- 可复用层次: + - 发票、贷项通知单和冲销; + - 伙伴、模块注册和工作流。 +- 成本与风险: + - 社区版与企业版边界复杂; + - 直接采用会偏离 Go 和 CLI-first。 +- 结论:仅参考会计与伙伴模型。 + +### 4.3 Twenty + +- 来源:[Twenty](https://github.com/twentyhq/twenty)。 +- 活跃度与技术栈:高;TypeScript、React、NestJS 和 PostgreSQL。 +- 许可证:仓库包含开源与商业边界,采用前必须逐文件核对。 +- 可复用层次: + - 现代 CRM 交互; + - 统一对象、筛选、视图和活动时间线。 +- 成本与风险: + - 技术栈与 HWLAB Vue 不同; + - 许可证与企业功能边界增加合规审查。 +- 结论:仅参考产品交互和对象模型。 + +### 4.4 EspoCRM + +- 来源:[EspoCRM](https://github.com/espocrm/espocrm)。 +- 活跃度与技术栈:高;PHP 和 JavaScript。 +- 许可证:AGPL-3.0。 +- 可复用层次:CRM 实体、角色、团队、关系和审计思路。 +- 成本与风险:AGPL 网络服务义务,且 PHP 技术栈不匹配。 +- 结论:仅参考,不复制源码。 + +### 4.5 Dolibarr + +- 来源:[Dolibarr](https://github.com/Dolibarr/dolibarr)。 +- 活跃度与技术栈:高;PHP。 +- 许可证:GPL-3.0。 +- 可复用层次: + - 轻量 ERP 和 CRM 模块边界; + - 第三方与发票关联。 +- 成本与风险:领域覆盖广但架构迁移成本较高,且存在 GPL 风险。 +- 结论:仅参考模块目录和业务关系。 + +### 4.6 OpenProject + +- 来源:[OpenProject](https://github.com/opf/openproject)。 +- 活跃度与技术栈:高;Ruby 和 TypeScript。 +- 许可证:GPL-3.0。 +- 可复用层次:项目、工作包、活动记录和权限矩阵。 +- 成本与风险:面向项目管理而非企业平台内核,技术栈与许可证不匹配。 +- 结论:不作为底座,仅参考工作项审计。 + +### 4.7 Documenso + +- 来源:[Documenso](https://github.com/documenso/documenso)。 +- 活跃度与技术栈:高;TypeScript。 +- 许可证:AGPL-3.0。 +- 可复用层次:文档签署状态、参与者、签署证据和模板体验。 +- 成本与风险: + - 电子签名涉及合规、身份与证据链; + - 存在 AGPL 风险。 +- 结论:首期仅预留集成边界,不内嵌源码。 + +### 4.8 Paperless-ngx + +- 来源:[Paperless-ngx](https://github.com/paperless-ngx/paperless-ngx)。 +- 活跃度与技术栈:高;Python 和 Django。 +- 许可证:GPL-3.0。 +- 可复用层次: + - 文档归档、标签和对应方; + - 全文检索、权限和消费管线。 +- 成本与风险: + - 适合作为独立文档系统,但不是合同事实主库; + - 存在 GPL 风险。 +- 结论:参考归档模型,未来可评估松耦合集成。 + +### 4.9 完整系统不直接采用的根因 + +- 产品边界不一致: + - ERPNext、Odoo 和 Dolibarr 以 ERP 全域为中心; + - Twenty 和 EspoCRM 以 CRM 为中心; + - OpenProject 以项目协作为中心; + - Documenso 和 Paperless-ngx 只覆盖文档生命周期的一部分。 +- 架构代价大于复用收益: + - 直接采用意味着把权限、扩展、数据迁移、前端和运维入口交给上游框架; + - PikaOA 仍需额外实现 CLI-first、YAML-first、UniDesk 交付和既定审计契约。 +- 许可证不确定性: + - GPL/AGPL 项目可合法研究、部署和集成,但复制、修改、分发或通过网络提供修改版时存在义务; + - PikaOA 的最终分发模式尚未确定,因此本阶段只提炼思想和公开接口,不复制实现。 + +## 5. 关键业务语义建议 + +### 5.1 合同不可变多版本 + +推荐把“合同身份”和“合同版本”分离: + +- `contract`: + - 保存稳定编号、业务伙伴、负责人、当前有效版本指针和总体状态; + - 不直接承载会被修订覆盖的条款正文。 +- `contract_version`: + - 保存版本号、结构化条款、金额、币种、日期、附件摘要、创建人和创建时间; + - `draft` 可编辑;一旦进入 `approved`、`signed`、`effective` 或 `superseded`,内容不可原地修改; + - 修订必须创建新版本,并记录 `previous_version_id`、修订原因和操作者。 +- 证据: + - 附件保存内容摘要、对象存储定位和媒体类型; + - 审批、签署、启用、终止和版本切换进入 append-only 审计记录; + - 查询必须能重建任一时点的有效版本。 + +该模型吸收 Frappe 的提交、取消、修订理念,但不复刻其 DocType 或框架实现。 + +### 5.2 发票作废而非物理删除 + +推荐状态至少区分: + +- `draft`:尚未形成对外事实,可按权限编辑或删除; +- `issued`:已开具,不允许物理删除或覆盖关键字段; +- `voided`:保留原编号、金额、关联合同与附件,并记录作废原因、时间和操作者; +- `credited`:未来需要会计冲销时,通过独立贷项记录关联原发票,不改写原事实。 + +约束: + +- 合同与发票使用稳定外键关联,同时保存开具时必要快照,避免伙伴名称后续变更破坏历史显示; +- `issued` 之后的任何纠正都产生新事实; +- 搜索默认可隐藏作废项,但审计、CLI 和明确过滤必须可查询; +- 数据保留策略不得把业务作废等同于数据库删除。 + +### 5.3 伙伴与甲方分类 + +采用统一 `business_partner`,不要为甲方、供应商、客户分别复制主表: + +- 稳定字段包括法定名称、统一标识、归档状态、联系人和地址; +- `partner_category` 支持层级、标签和有效期; +- “甲方”“供应商”“客户”是上下文角色或分类,可同时存在; +- 合同保存签约时的伙伴快照和角色,伙伴主数据后续变更不覆盖历史合同; +- 分类变更必须审计,归档代替物理删除。 + +### 5.4 员工、身份与权限 + +- 身份与员工档案分离: + - 身份负责登录、会话和外部身份提供方映射; + - 员工负责组织、岗位、在职状态和业务归属。 +- 首期采用 RBAC: + - 资源与动作使用稳定 capability; + - 角色只聚合 capability; + - 数据范围通过明确条件实现,不把前端路由可见性当作后端授权。 +- `Casbin` 适合首期进程内策略判定; +- 当出现跨服务关系授权、对象级共享或多租户关系图时,再评估 `OpenFGA`。 + +### 5.5 审计与 outbox + +- 业务写入、审计事件和 outbox 记录必须在同一 PostgreSQL 事务提交; +- outbox 记录包含稳定事件类型、聚合 ID、聚合版本、发生时间和脱敏载荷; +- worker 以至少一次语义处理,消费者通过事件 ID 或业务幂等键去重; +- `Watermill` 负责消息抽象和处理管线,不替代数据库事务真相; +- 审计记录和集成事件分开: + - 审计面向人和合规追溯; + - outbox 面向系统集成和未来服务提取。 + +### 5.6 模块扩展与未来微服务提取 + +首期保持模块化单体: + +- 每个模块拥有自己的 handler、use case、repository、迁移和事件定义; +- 跨模块写入只能通过应用服务或已声明接口,不允许直接修改他模块表; +- 共享内核只保留身份、伙伴、附件、审计、分页、错误和幂等契约; +- 只有满足以下事实后才提取微服务: + - 独立扩缩容或故障隔离需求持续存在; + - 数据所有权和事件契约稳定; + - 跨模块同步事务已消除; + - 独立部署收益高于网络、可观测性和运维成本。 + +## 6. Go 后端组件评估 + +### 6.1 直接采用 + +- HTTP: + - [chi](https://github.com/go-chi/chi),MIT; + - 轻量、标准库兼容、路由组合自然,适合模块化单体。 +- PostgreSQL: + - [pgx](https://github.com/jackc/pgx),MIT; + - PostgreSQL 原生能力完整,适配事务、批量和通知。 +- SQL 代码生成: + - [sqlc](https://github.com/sqlc-dev/sqlc),MIT; + - SQL-first、静态类型,便于审查真实查询。 +- 数据库迁移: + - [goose](https://github.com/pressly/goose),MIT; + - 简单、Go 生态成熟,适合显式 SQL 迁移。 +- CLI: + - [Cobra](https://github.com/spf13/cobra),Apache-2.0; + - 子命令和 help 生态成熟,输出契约仍遵循 PikaOA CLI 规格。 +- RBAC: + - [Casbin](https://github.com/casbin/casbin),Apache-2.0; + - 进程内、模型灵活,首期运维成本低。 +- 事件: + - [Watermill](https://github.com/ThreeDotsLabs/watermill),MIT; + - 消息处理抽象成熟,可与事务 outbox 结合。 + +### 6.2 仅比较或预留 + +- [Echo](https://github.com/labstack/echo),MIT: + - 功能完整但约定较多; + - 不与 chi 并用,仅在发现明确缺口时重新评估。 +- [Gin](https://github.com/gin-gonic/gin),MIT: + - 生态和认知度高,但自有 Context 侵入更明显; + - 不采用,避免无收益的框架抽象。 +- [Atlas](https://github.com/ariga/atlas),Apache-2.0: + - 部分能力与商业产品边界需核验; + - 声明式 schema 与检查能力强,但会引入第二套迁移模型; + - 首期不采用。 +- [OpenFGA](https://github.com/openfga/openfga),Apache-2.0: + - 适合复杂对象关系授权; + - 会增加独立服务和模型治理; + - 预留边界,首期不采用。 +- [Asynq](https://github.com/hibiken/asynq),MIT: + - Redis 队列成熟; + - 会增加首期基础设施和第二事实源; + - 首期不采用。 + +### 6.3 推荐最小组合 + +```text +Cobra CLI / Vue Web + | + chi HTTP + | +应用服务与模块边界 + | +sqlc + pgx + PostgreSQL + | +业务表 + audit_log + outbox + | +Watermill worker / 外部集成 +``` + +组合原则: + +- 不引入 ORM 作为默认数据访问层; +- 不同时维护 `goose` 与 `Atlas` 两套迁移真相; +- 不为异步任务额外引入 Redis,除非后续有独立证据; +- CLI 和 Web 必须调用同一 HTTP API 与业务用例,不形成旁路管理逻辑。 + +## 7. Vue 3 与 HWLAB v0.3 复用边界 + +### 7.1 直接采用 + +| 组件 | 许可证 | 用途 | +| --- | --- | --- | +| [Vue 3](https://github.com/vuejs/core) | MIT | 组件与响应式基础 | +| [Vue Router](https://github.com/vuejs/router) | MIT | 路由、模块入口和守卫 | +| [Pinia](https://github.com/vuejs/pinia) | MIT | 会话、访问摘要和跨页面客户端状态 | +| [Tailwind CSS](https://github.com/tailwindlabs/tailwindcss) | MIT | 设计令牌与响应式布局 | + +### 7.2 复用 HWLAB v0.3 的内容 + +- 复用同族技术栈、设计语言和已验证的响应式布局方法; +- 复用以下模式,而不是复制 HWLAB 业务模块: + - 应用壳、侧边导航、顶栏、内容区和移动端折叠逻辑; + - 登录态、路由守卫、403/404 和 API 错误呈现; + - 表格筛选、分页、详情抽屉、时间线和状态徽标; + - 可访问性、加载态、空态和失败可见性; + - 与 CLI 同源的 capability 驱动导航。 + +### 7.3 禁止复用 + +- 不复制 Workbench、AgentRun、Code Queue 等领域组件和状态投影; +- 不把 HWLAB 的 session、run、event 模型引入合同或发票领域; +- 不让前端 Pinia store 成为业务事实真相; +- 不在 CLI 后端契约完成前先冻结 Web 私有接口。 + +## 8. 可观测性方案 + +| 组件 | 许可证 | 结论 | +| --- | --- | --- | +| [OpenTelemetry Go](https://github.com/open-telemetry/opentelemetry-go) | Apache-2.0 | 直接采用,负责 trace、metric 和 context 传播 | +| [OpenTelemetry Collector](https://github.com/open-telemetry/opentelemetry-collector) | Apache-2.0 | 直接采用现有平台能力,应用只发 OTLP | +| [Prometheus Go client](https://github.com/prometheus/client_golang) | Apache-2.0 | 直接采用,暴露低基数业务与运行指标 | +| [Tempo](https://github.com/grafana/tempo) | AGPL-3.0 | 复用 UniDesk 独立运行服务,不把源码或服务端实现嵌入 PikaOA | + +### 8.1 关联方式 + +- HTTP、CLI 请求和 worker 消费均传播 `trace_id` 与 `span_id`; +- 结构化日志至少包含: + - 时间、级别、服务、模块、事件名; + - `trace_id`、`span_id`、request ID; + - 脱敏后的 actor、聚合类型和聚合 ID; + - 稳定错误码,不记录 Secret、令牌或合同敏感正文。 +- 指标保持低基数: + - 请求量、错误量、延迟; + - outbox backlog、处理成功和失败; + - 合同与发票状态变化计数; + - 禁止把员工 ID、合同 ID、发票号作为 metric label。 +- Collector、采样、保留和导出参数继续由 owning YAML 控制,本报告不固化数值。 + +## 9. 许可证边界 + +本节是工程风险提示,不替代法律意见。 + +- MIT、Apache-2.0: + - 可作为首选依赖; + - 仍需保留许可证和版权通知,并维护依赖清单。 +- LGPL-3.0: + - 动态链接、修改库和分发场景有不同义务; + - Odoo 必须按核心、社区模块、企业模块逐项确认,不以仓库总体印象替代检查。 +- GPL-3.0: + - ERPNext、Dolibarr、OpenProject 和 Paperless-ngx 等项目只提炼公开业务思想; + - 禁止复制源码、迁移脚本、模板或前端组件进入闭源可能性未知的仓库。 +- AGPL-3.0: + - EspoCRM、Documenso 和 Tempo 等网络服务软件需要特别审查修改版网络提供义务; + - 优先采用进程外、协议级集成,并保留独立部署和许可证材料; + - 任何修改、再分发或嵌入决定必须先完成法律与架构审查。 +- 上游可能调整许可证或采用多许可证: + - 实现任务必须锁定 commit/tag; + - 对锁定版本重新读取 `LICENSE`、`NOTICE`、依赖清单和商业功能说明; + - 自动生成软件物料清单并在发布前执行许可证扫描。 + +## 10. 实施建议 + +### 10.1 首期基线 + +- 建立 Go 模块化单体与单一 PostgreSQL 数据库; +- 用 chi、sqlc、pgx、goose、Cobra 建立最小 API/CLI 骨架; +- 先实现员工/RBAC、伙伴、合同版本、发票作废、审计和 outbox; +- 用 Casbin 做 capability 判定,策略存储与业务事务边界明确分离; +- 用 Watermill worker 消费 PostgreSQL outbox; +- 接入 OpenTelemetry Go、OTLP 和 Prometheus 指标; +- CLI 验收通过后再实现 Vue 3 Web。 + +### 10.2 需要保留的替换边界 + +- HTTP 框架只暴露在 transport 层,应用用例不依赖 chi 类型; +- Casbin 通过授权接口接入,未来可替换或桥接 OpenFGA; +- Watermill 通过事件发布与消费接口接入,未来可迁移 Kafka 等 broker; +- 对 Documenso、Paperless-ngx 等系统只定义外部连接器,不共享业务数据库; +- Tempo 作为 OTel 后端,不让业务代码依赖 Tempo 私有 API。 + +### 10.3 后续任务门槛 + +- R1.2 建仓前: + - 确认最终 Go module、Node package 和许可证清单; + - 明确依赖锁定和 SBOM 生成入口。 +- R1.3 实现前: + - 先把合同版本、发票作废、伙伴角色、授权和 outbox 写成 API/CLI 验收契约; + - 禁止从完整开源系统复制 schema 或代码。 +- R1.4 Web 开发前: + - CLI 后端主路径通过; + - 明确 HWLAB 可复用的布局、基础组件和设计令牌清单; + - Web 不得创建后端没有的隐式状态。 +- 评估微服务前: + - 收集独立扩缩容、故障隔离、团队所有权和数据边界证据; + - 没有证据时继续保持模块化单体。 + +## 11. 来源索引 + +### 11.1 业务系统 + +- ERPNext 仓库: +- Frappe 仓库: +- Frappe 单据状态文档: +- ERPNext 不可变账本说明: +- Odoo 仓库: +- Odoo 许可证说明: +- Odoo 贷项与退款文档: +- Twenty 仓库: +- EspoCRM 仓库: +- Dolibarr 仓库: +- OpenProject 仓库: +- Documenso 仓库: +- Paperless-ngx 仓库: +- Paperless-ngx 权限文档: + +### 11.2 Go 组件 + +- chi: +- Echo: +- Gin: +- pgx: +- sqlc: +- goose: +- Atlas: +- Cobra: +- Casbin: +- OpenFGA: +- Watermill: +- Asynq: + +### 11.3 前端与可观测性 + +- Vue 3: +- Vue Router: +- Pinia: +- Tailwind CSS: +- OpenTelemetry Go: +- OpenTelemetry Collector: +- Prometheus Go client: +- Tempo: + +## 12. 风险与未决项 + +- Odoo、Twenty、Atlas 等项目存在模块级、目录级或商业能力边界,不能只看仓库首页许可证; +- 电子签名、发票与会计凭证的法律效力依赖适用地区,后续需求需单独合规确认; +- Casbin 足以覆盖首期 RBAC,但对象级共享和关系授权增长后可能需要 OpenFGA; +- PostgreSQL outbox 可满足首期,但高吞吐、多消费者和跨区域需求出现后可能需要 Kafka 等 broker; +- HWLAB v0.3 的具体组件可复用清单应在 R1.4 基于当时源码逐项确认; +- 本报告没有发现阻塞 PJ2026-03 继续执行的问题。