UNPKG

@lark-project/cli

Version:

飞书项目插件开发工具

38 lines (31 loc) 7.61 kB
--- name: meegle-plugin-backend version: 1.0.0 description: | Meegle 插件「自建后端」开发知识参考——接收并验签 webhook 回调、调 Meegle OpenAPI、把结果写回工作项 / AI 节点 / AI 字段、给前端组件做 `/api/proxy/*` 代理、用 `lpm perm` 开通 OpenAPI scope。 这是**知识参考**(告诉你每类后端知识从哪取、哪些是带源可验的事实),**不是开发流程**——什么时候做什么由调起本 skill 的上层编排流程决定,本 skill 不规定顺序、不编排步骤。 触发:用户问 / 做 Meegle 插件的服务端那一半(webhook 怎么收 / 怎么验签、OpenAPI 用哪些 / 怎么调、权限怎么开、写回怎么做、后端代理怎么写),或被上层编排流程在命中后端时调起取知识。 metadata: requires: bins: ["npx"] cliHelp: "lpm --help" --- # Meegle 插件后端开发知识(参考) 「接飞书项目后端」的知识索引——**告诉你每类知识从哪取**。本 skill 不编排流程、不规定顺序、不带步骤:什么时候做什么由调起本 skill 的上层编排流程决定。本 skill **自足**,不依赖任何外部 skill 的 reference。 ## 两条贯穿原则 - **平台事实带源、查不到即停**:碰平台的每一处(webhook 验签、token 获取、OpenAPI 出入参、scope、写回)都要能指回下面列出的源;**MCP / schema 查不到就停下问用户,绝不编造**(凭经验拼的 OpenAPI 签名能过编译但运行时跑废——这是 ai_node 评测里弱 AI 编造签名的教训)。这里的源是**真实可访问的外部出处**——写后端代码时**在 OpenAPI 调用邻近用 `// source: <MCP 查到的接口 doc>` 标出**(接口签名/出入参的依据来自 MCP,不是 `lpm perm list`——后者只给「能不能调」的 scope 目录),签名最易编造的手写 HTTP 尤其要标,方便联调和后续核对。 - **代码落地交接、不保证**:上面那些平台事实可验证;把它们拼成的后端代码跑在沙盒外、`lpm` 不碰它、没有 `lpm build` / `tsc` 反馈环——代码跑不跑得对,由你 / 你的 agent 在自己环境联调验证。 ## 知识从哪取 - **后端代码在哪 / 边界**:后端代码跑在你自己的仓 / 服务里(**不在插件工程目录**)。本 skill 只指导「碰平台那几块」(webhook 接收+验签 / 调 OpenAPI / 写回 / `/api/proxy/*` 代理)怎么写,**不 scaffold 整个后端**——框架 / 语言 / 目录结构 / 业务逻辑 / 部署是你自己的技术方案。 - **webhook 验签 + 事件协议**:MCP 关键词 `兼容性说明与验签说明` / `webhook 签名校验`(验签细节在这两篇;`飞项插件 自建后端 鉴权` 召回的是 MCP Server 配置、不含验签算法)。验签是**裸 `sha256(plugin_id + request_time + token)`** 顺序拼接(`token` = 点位上配的回调 token),且 `signature` / `request_time` 是**请求体字段、不在 HTTP header**——**不是 HMAC、`pluginSecret` 不参与验签**(这条最易凭直觉编成 `HMAC(body, key=pluginSecret)` + 读 header,务必照源核)。 - **AI 点位的事件协议**`ai_node` / `ai_field` 的事件结构在 schema description 里:`lpm --cwd "$PLUGIN_DIR" schema``lpm --cwd "$PLUGIN_DIR" ai peek <schema 路径> AINodePoint`(或 `AIFieldPoint`)。 - **webhook url/token 配在点位哪个字段**(按点位类型):`ai_node` / `ai_field` 在某个 `listen_event` extension 里、不在点位顶层;`intercept` / `listen_event` 在点位顶层 `url`(+ `token`);`control`(嵌新建页等场景)在 `control[].url` - **已知现象**`ai_node` / `ai_field` 的 url/token 走 `local-config set → update → get --remote` 往返后,`lpm local-config diff` 对这些点位**恒报 `[MODIFIED]`**(读端点 `GetPointInfoByPluginKey` 没把 `listen_event` extension 里的 url/token 回填)——**不阻断、不是改错了**`listen_event` extension 里有值、`publish` 出来的插件正常),照常 `update` 推上去即可。 - **这个 app 能调哪些 OpenAPI(+ scope + doc URL)**:把要调的接口丢 `lpm perm check --apis <a,b,c>` 拿判决(CLI 已替你把「接口 → 归属 scope → 在不在已开通」反查好)——`satisfied` 可直接调;`needApply``normal` 工程缺、由插件会话用 `lpm perm apply` 申请后才可调;`ai_node` / `ai_field` 权限创建时全开、恒 `satisfied`,没有申请这一步(`perm apply` 在 AI 应用上不可用),`lpm perm list``granted` 即可;`unknown` 是此 app 目录里没这接口。要总览能力天花板用 `lpm perm list``granted` 已开通可调 / `applicable` 还能申请,各含覆盖的 OpenAPI;`--raw` 出原始 `perm_meta[].resource[]`)。坐在自己后端仓里、读不到 `plugin.config.json` 时,给 `perm check` / `perm list``--plugin <pluginId> --site-domain <开发者站点 origin>` 可 token-only 在任意目录查(首次带 flag 后该插件记进 `~/.lpm/` 全局注册表,之后可省略 flag)。 - **OpenAPI 出入参签名 + 鉴权 / token 获取流程**:出入参用 MCP 关键词 `<perm list/check 给的接口中文名> OpenAPI`(如 `获取工作项详情 OpenAPI` / `完成 AI 节点 OpenAPI`);鉴权 + token 获取用 `Open API 概述`(鉴权 Header 表在此篇)/ `获取访问凭证`**鉴权 header 是 `X-PLUGIN-TOKEN`(用插件身份须同时配 `X-USER-KEY`),不是 `Authorization: Bearer`**;这个 token 是**单独取的 `plugin_access_token`,与 webhook 回调 token 是两套独立凭证**——别拿 webhook 事件里的 token 当 OpenAPI 鉴权(最常见的双重编造)。命中 JSSDK / 总览而非接口规格时,换属性词重试(`OpenAPI``接口``权限`);别用英文 API 名(命中前端 JSSDK 错文档)。 - **用 SDK 还是手搓 HTTP**:Go / Java **优先用官方服务端 SDK**`larksuite/project-oapi-sdk-golang` / `project-oapi-sdk-java`,封装 OpenAPI 出入参 + 自动管 token 与鉴权 header,用法走 MCP 关键词 `飞项 服务端 SDK` / `project-oapi-sdk 使用`)——用 SDK 则上面 `X-PLUGIN-TOKEN` / token 获取由 SDK 代办、免手填出错;**别在有 SDK 的语言里手搓 HTTP**。TS / Node **无**官方 SDK → 只能逐接口查文档手写 HTTP,签名最易编造,尤其严守"无源即停"。 - **写回**`ai_node` 调「完成 AI 节点」(用 webhook 解出的 `work_item_id` + `node_uuid` 定位);`ai_field` 用 webhook 的 `field_ai_entity.task_id` 调「更新 AI 字段」回传 `field_value``work-item` 调「更新字段」。接口出入参 MCP 查。 - **前端要平台数据的 `/api/proxy/*` 代理**:动线 = 前端 `fetch('/api/proxy/X')` → 后端持凭据调 OpenAPI → 返回前端期望形态;token 拼装走 MCP(关键词同上「鉴权」),不把 token 放进前端 bundle。 - **凭据**:放后端环境变量,代码只写 `process.env.<变量名>` 引用;真值由用户设进 env,AI 不读、不回显,**不从 `plugin.config.json` grep / decrypt `pluginSecret` 粘进代码**(那是把凭据泄漏进产物)。 - **后端运行时不依赖** `lark-project` / `lpm`:它们是开发期本地工具、无运行时鉴权与 SLA;运行时拿数据只走上面的 OpenAPI 三段动线。 - **交接包格式**(把上面带源事实落成一份 md,交给当前会话写代码 / 留给后续接手的人或 agent):见 [`backend-handoff.md`](references/backend-handoff.md)。