From 2fc1b31d3f2f4e366759a449f4f193edec35e82b Mon Sep 17 00:00:00 2001 From: nac Date: Sun, 12 Jul 2026 22:34:17 +0000 Subject: [PATCH] docs: add project write design --- .../specs/2026-07-12-project-write-design.md | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 docs/superpowers/specs/2026-07-12-project-write-design.md diff --git a/docs/superpowers/specs/2026-07-12-project-write-design.md b/docs/superpowers/specs/2026-07-12-project-write-design.md new file mode 100644 index 0000000..57a5fca --- /dev/null +++ b/docs/superpowers/specs/2026-07-12-project-write-design.md @@ -0,0 +1,133 @@ +# 项目写入与附件上传设计 + +## 目标 + +为现有只读 NocoBase CRM MCP 增加受限的项目创建与更新能力,并支持通过同一 HTTP 服务上传文件、再将其增量关联到项目附件。 + +范围仅覆盖 NocoBase 项目集合 `t_projects`。服务不得提供任意集合、任意字段或删除项目的能力。 + +## 已确认的数据模型 + +项目集合:`t_projects`(标题:项目)。 + +| MCP 参数 | NocoBase 字段 | 说明 | +| --- | --- | --- | +| `name` | `f_project_name` | 项目名;创建时必填 | +| `customer_id` | `client_ID` | 客户外键,目标集合为 `t_nt3pjadelqi` | +| `inquiry_date` | `xm_project_inquiry_date` | 项目收到日期,`YYYY-MM-DD` | +| `progress` | `f_projects_progress` | 项目进展 | +| `applications` | `f_projects_applications` | 应用 | +| `part_numbers` | `f_projects_part_numbers` | 涉及产品料号 | +| `period_usage` | `f_projects_period_usage` | 项目用量 | +| `details` | `f_projects_details` | 详细信息 | + +附件关联字段为 `f_projects_attachments`,类型为 `belongsToMany`,目标为 NocoBase 内置 `attachments` 集合,存储为 `local`。联系人、跟进记录、项目情况更新、系统字段和其它字段均不在首版写入范围内。 + +允许的项目进展为:`询价阶段`、`已报价`、`送样`、`已定点`、`SOP`、`终止`。MCP 接受这些中文标签,并映射到 NocoBase 已配置的内部枚举值。 + +## 方案选择 + +采用分步上传方案:HTTP 上传端点先将文件写入 NocoBase 附件库并返回附件 ID;MCP 项目工具再使用该 ID 建立项目关联。 + +此方案将二进制 multipart 上传与 MCP JSON 工具调用分开,便于客户端重试、明确上传与项目写入的失败边界,也避免客户端持有 NocoBase JWT。单请求中同时提交项目和文件、以及让客户端直接调用 NocoBase 均不采用。 + +## HTTP 上传接口 + +新增 `POST /uploads`,与 `/mcp` 部署在同一个 HTTP 服务中,并复用现有 MCP Bearer Token 中间件。 + +请求必须为 `multipart/form-data`,每次仅接收一个名为 `file` 的文件字段。默认单文件上限为 25 MiB。首版不额外限制 MIME 类型;部署者可在配置中收紧允许的类型。 + +服务将文件流式写入受控临时目录,随后转发到 NocoBase: + +`POST /attachments:create?attachmentField=t_projects.f_projects_attachments` + +转发请求使用 `NOCOBASE_MCP_UPLOAD_JWT` 中配置的 NocoBase 用户 JWT。该 JWT、NocoBase API 地址和文件内容均不得写入日志、MCP 结果或 `config.json`。临时文件无论成功或失败都必须立即清理。 + +成功响应: + +```json +{ + "upload_id": 123, + "filename": "quote.pdf", + "size": 456, + "mimetype": "application/pdf" +} +``` + +`upload_id` 是 NocoBase `attachments.id`。上传成功但尚未关联到项目的附件会保留;首版不运行自动清理任务,以避免误删业务文件。 + +## MCP 工具 + +新增: + +```text +create_project( + name, customer_id?, inquiry_date?, progress?, + applications?, part_numbers?, period_usage?, details?, + attachment_ids? +) + +update_project( + project_id, + name?, customer_id?, inquiry_date?, progress?, + applications?, part_numbers?, period_usage?, details?, + add_attachment_ids?, remove_attachment_ids? +) +``` + +### 规则 + +- `name` 创建时必填,且去除首尾空白后不能为空。 +- `inquiry_date` 必须为 `YYYY-MM-DD`。 +- `progress` 必须是上表中定义的六个中文标签之一。 +- `customer_id` 只写入 `client_ID`。 +- `attachment_ids` 仅用于创建后建立附件关联。 +- 更新附件只接受 `add_attachment_ids` 和 `remove_attachment_ids`;不提供覆盖整个附件集合的语义。 +- 同一个附件 ID 不得同时出现在 add 和 remove 列表中。 +- 输入列表必须去重;不存在或无权访问的附件使该次附件关联操作失败。 + +创建或更新标量字段后,再执行附件关联。若关联操作失败,响应必须包含已创建或已更新的 `project_id` 和结构化失败详情;不回滚已经成功写入的项目字段。关联操作使用 NocoBase `belongsToMany` 的 `add` 与 `remove` 资源操作。 + +## 错误契约 + +所有业务失败均保持现有 MCP 的结构化错误格式。首版增加: + +- `invalid_project_input` +- `invalid_progress` +- `project_not_found` +- `attachment_not_found` +- `upload_too_large` +- `unsupported_media_type` +- `nb_upload_failed` +- `nb_upload_unauthorized` + +上传端点对缺失或无效的 MCP Bearer Token 返回 401。上游 JWT 失效或被拒绝时,上传端点返回明确的认证失败,不重试登录,也不暴露上游令牌。 + +## 配置与权限 + +`config.json` 追加固定的 `projects` 映射,包含项目资源、八个可写字段、客户外键和附件关联字段。该映射不允许调用方覆盖。 + +运行时环境变量: + +- `NOCOBASE_MCP_UPLOAD_API_BASE_URL` +- `NOCOBASE_MCP_UPLOAD_JWT` +- `NOCOBASE_MCP_UPLOAD_MAX_BYTES`(默认 `26214400`) +- 可选 MIME 白名单环境变量或配置项 + +服务角色必须拥有:`t_projects` 的 create/update、`attachments` 的上传/create,以及 `t_projects.f_projects_attachments` 的 add/remove 权限。README 和 systemd 服务配置必须明确这些新增权限与密钥配置。 + +## 验证 + +- 为 NocoBase 客户端新增创建、更新和关联 add/remove 的命令构造单元测试。 +- 为项目服务增加字段白名单、日期、进展、附件冲突和结构化错误测试。 +- 为上传 ASGI 接口增加认证、multipart、文件上限、上游失败和临时文件清理测试。 +- 为 MCP server 增加新工具的 schema、参数传递和附件增量语义测试。 +- 自动化测试全部使用模拟的 NocoBase/HTTP 调用;不得连接真实 NocoBase 或写入真实项目、附件。 + +## 非目标 + +- 删除项目或附件。 +- 管理联系人、跟进记录、项目更新记录或任意其它关联。 +- 任意字段写入或调用方指定资源。 +- 自动清理未关联附件。 +- 客户端直接持有或提交 NocoBase JWT。