资讯详情

Activepieces Piece Sets 详解:平台级 Piece 可见性配置的读取时派生架构

📅 2026/9/15 12:47:31 | 华诺云谱 👁 阅读
Activepieces Piece Sets 详解:平台级 Piece 可见性配置的读取时派生架构
Activepieces Piece Sets 详解平台级 Piece 可见性配置的读取时派生架构【免费下载链接】activepiecesAI Agents MCPs AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepiecesPiece Sets 是 Activepieces 面向平台管理员提供的具名、可复用的 Piece/动作/触发器可见性配置管理员定义一次即可批量应用到多个项目用于在多租户平台尤其 Embed 场景中精准控制某个项目能使用哪些 Piece 及其动作/触发器。本文基于仓库中的 piece-sets.md 知识文档结合服务端、共享模型与 Web 前端的真实源码完整讲解其数据模型、读写 API、读取时派生read-time derived的设计原理、迁移路径、权限模型与常见陷阱帮助开发者掌握该功能的配置方法与底层实现。Piece Sets 是什么在 Activepieces 中一个平台platform下通常存在多个项目project不同项目可能面向不同客户、不同业务线需要看到不同的 Piece 集合。Piece Sets 把可见性配置抽象成平台级对象解决的核心问题是管理员配置一次多个项目共享同一份可见性规则。Piece Sets 的可见性是在读取时read time派生的——当列出 Piece 或组件action/trigger时实时计算可见性安装新 Piece 时不会写入任何东西。这与传统安装时把新 Piece 写入黑名单的模式有本质区别详细设计背景见 ADR 000007Piece-set visibility is derived at read time。从定位上看Piece Sets 属于 EE/Cloud企业版/云版能力受platform.plan.managePiecesEnabled开关控制在 CE社区版或开关关闭时Piece Set 不生效过滤会回退到旧的项目级 plan allow/block list机制。数据模型PieceSetConfig可见性配置本体配置是一个 JSONB 结构其 TypeScript 定义位于 packages/core/shared/src/lib/ee/piece-set/index.ts核心结构为export const PieceSetConfig z.object({ pieces: PieceSelection.default({ mode: PieceSelectionMode.INCLUDE_ALL, exceptions: [] }), selectedActions: z.record(z.string(), z.array(z.string())).default({}), selectedTriggers: z.record(z.string(), z.array(z.string())).default({}), })pieces: PieceSelection——Piece 层面的选择策略见下文selectedActions: Recordpiece, action[]——按 Piece 记录的被精选curated动作白名单selectedTriggers: Recordpiece, trigger[]——按 Piece 记录的触发器白名单。PieceSelectionPiece 层面的两种模式export enum PieceSelectionMode { INCLUDE_ALL include_all, EXCLUDE_ALL exclude_all, } export const PieceSelection z.object({ mode: z.enum([PieceSelectionMode.INCLUDE_ALL, PieceSelectionMode.EXCLUDE_ALL]).default(PieceSelectionMode.INCLUDE_ALL), exceptions: z.array(z.string()).default([]), })两种模式语义相反但都用同一套exceptions数组模式含义对新 Piece 的处理include_all默认所有 Piece 可见exceptions中的除外自动包含未来新安装的 Pieceexclude_all只有exceptions中的 Piece 可见未来新 Piece 自动隐藏例如{ mode: include_all, exceptions: [activepieces/piece-slack] }表示除了 Slack 之外全部可见而{ mode: exclude_all, exceptions: [activepieces/piece-slack] }表示只有 Slack 可见。精选组件selected components语义在selectedActions/selectedTriggers中某个 piece key 出现即表示该 Piece 被精选只有列出的组件可见未来新增的组件保持隐藏。key 不出现则代表该 Piece 的所有组件含未来新增全部可见。注意这里没有模式字段——组件层面是严格的全量 vs 精选二选一ADR 000007 明确指出组件层加 mode 是死重dead weight。PieceSet 实体与索引piece_set实体定义在 piece-set.entity.ts关键字段platformId——所属平台onDelete: CASCADE外键fk_piece_set_platform_idname——具名配置名称key——Embed 句柄embed handle平台内唯一自动生成规则为kebabCase(name)-random 8 位见resolveKeypiece-set.service.tsisDefault——是否默认集配合部分唯一索引idx_piece_set_platform_id_is_defaultWHERE isDefault true保证每个平台只有一个默认集config——上述 JSONB 配置默认值为{ pieces: { mode: include_all, exceptions: [] }, selectedActions: {}, selectedTriggers: {} }。项目通过project.pieceSetId引用 Piece Set删除集时该引用SET NULL见文档描述服务端删除逻辑会把项目重新指回默认集见下文。Default Set每个平台的兜底每个平台有且仅有一个默认集isDefault: truekey: default未分配 Piece Set 的项目自动解析到默认集默认集不可删除——服务端delete会抛出VALIDATION错误Cannot delete the default piece setpiece-set.service.ts删除非默认集时所有引用它的项目会被重新指回默认集然后才删除该集同一事务内完成新项目创建时ee-project-hooks.ts 在postCreate钩子中为其分配默认集在managePiecesEnabled开启的前提下。默认集的获取使用了分布式锁getOrCreateDefaultPieceSet先无锁查询一次未命中则通过distributedLock(log).runExclusive({ key: piece_set_default_platformId, timeoutInSeconds: 60 })二次确认后创建避免并发下重复建默认集。核心设计可见性在读取时派生为什么放弃安装时写入模式旧模型是黑名单deny-listdisabledPieces加策略标志。它的致命问题是黑名单无法声明式表达隐藏还不存在的东西于是每次元数据创建都会触发onPieceCreated钩子——包括每小时跨平台运行的PIECES_SYNCcron——遍历每个 Piece Set 把新 Piece 物化进黑名单黑名单随之无界增长。新模型改为存储可见白名单让新 不在列表 隐藏自动成立彻底删除了安装时的写扩散write-on-install fan-out。该决策记录在 ADR 000007。两个纯函数解析器共享解析器isPieceVisible/isComponentVisible位于共享层 index.ts服务端与 Web 前端共用export function isPieceVisible({ pieces, name }: { pieces: PieceSelection, name: string }): boolean { const listed pieces.exceptions.includes(name) return pieces.mode PieceSelectionMode.INCLUDE_ALL ? !listed : listed } export function isComponentVisible({ selected, name }: { selected: string[] | undefined, name: string }): boolean { if (isNil(selected)) { return true } return selected.includes(name) }isComponentVisible中selected为undefined即代表未精选返回true全可见与数据模型语义严格对应。服务端解析流程服务端在 piece-filtering-utils.ts 的resolveVisibility中应用解析版本门槛仅ENTERPRISE/CLOUD版本返回策略其他版本返回null不启用过滤参数门槛platformId或projectId任一为 nil直接返回null不过滤解析项目所属 Piece SetresolvePieceSetForProject通过projectRepo().findOneBy({ id: projectId })查项目取project.pieceSetId为空或集已不存在时回退到getOrCreateDefaultPieceSet(platformId)构建策略buildPolicy生成VisibilityPolicy包含isPieceVisible、filterPieces、filterComponents过滤suggestedActions/suggestedTriggers和filterPieceComponents过滤单个 Piece 的actions/triggers字典四个能力。值得注意没有安装时同步也没有onPieceCreated钩子解析纯粹发生在读取路径上。这也解释了为什么 Piece 改名会被当作新 Piece——新名字不在列表里自然隐藏直到被重新选中。REST API/v1/piece-sets路由由 piece-set.controller.ts 注册整个模块受managePiecesEnabled开关门控模块级preHandler钩子platformMustHaveFeatureEnabled见 piece-set.module.ts且安全级别为platformAdminOnly仅 USER 与 SERVICE 两类主体。方法路径说明GET/v1/piece-sets分页列出平台的 Piece Setslimit默认 10、最大 100游标分页POST/v1/piece-sets创建body 只需name可选keyGET/v1/piece-sets/:id获取单个POST/v1/piece-sets/:id更新声明式合并见下文DELETE/v1/piece-sets/:id删除默认集拒绝删除POST/v1/piece-sets/:id/duplicate复制body 传namePOST/v1/piece-sets/:id/projects批量分配项目body{ projectIds: string[] }至少 1 个DELETE/v1/piece-sets/:id/projects/:projectId移除单个项目的分配默认集拒绝移除更新语义ComponentIntent 与声明式合并更新请求体index.ts允许部分更新name、key、pieces、actions、triggers均可选。其中actions/triggers使用ComponentIntent判别联合export const ComponentIntent z.discriminatedUnion(mode, [ z.object({ mode: z.literal(all) }), z.object({ mode: z.literal(selected), selected: z.array(z.string()) }), ]){ mode: all }——把该 Piece 重置为全部组件可见在合并时删除该 piece 的精选键{ mode: selected, selected: [...] }——设置白名单selected: []空数组表示隐藏全部组件。合并逻辑在 piece-set-config.ts 的pieceSetConfig.applyUpdateapplyUpdate({ current, request }): PieceSetConfig { return { pieces: request.pieces ?? current.pieces, selectedActions: applyComponentIntents({ current: current.selectedActions, intents: request.actions }), selectedTriggers: applyComponentIntents({ current: current.selectedTriggers, intents: request.triggers }), } }applyComponentIntents只操作请求中出现的 piece 键永不触碰未被引用的组件键Object.entries(intents).reduce从current累积从而实现声明式合并。注意更新是 last-writer-wins随着后台写入者被移除唯一并发写者只剩两个管理员同时编辑同一集这是 ADR 000007 明确的取舍。服务端更新还会校验 key 冲突捕获 PostgreSQL23505唯一冲突并转为VALIDATION错误Piece set key already used。权限与门控细节整个模块被 feature flag 门控/v1/piece-sets的全部路由含GET都受platform.plan.managePiecesEnabled控制。当平台计划锁定、flag 关闭时Web 端的列表查询piece-sets-hooks.ts 中usePieceSets/usePieceSet以enabled: platform.plan.managePiecesEnabled直接禁用表格为空行操作永不渲染因此只有工具栏/入口点需要 UI 守卫LockedAlertRequestTrial featureKeyENTERPRISE_PIECES只需在PlatformPiecesPage上、tabs 上方放置一次同一个 flag 同时门控 Pieces 与 Piece Sets 两个 tab详情路由直接重定向回 tab而不是挂在一个永远不会运行的查询的 spinner 上。读取时派生是否被门控与 API 模块不同resolveVisibility的派生解析不依赖managePiecesEnabled仅依赖版本与参数是否齐全。而 Embed 端的强制applyProjectPieceAccess同样无条件执行不因 flag 关闭而跳过。GET /v1/pieces 的 projectId 查询参数三条GET /v1/pieces*路由的 route security 是securityAccess.unscoped(ALL_PRINCIPAL_TYPES)但接受projectId查询参数来选择用哪个项目的 Piece Set 过滤结果。处理器内部通过rbacService.assertPrinicpalAccessToProject自行断言项目成员关系仅成员关系、无权限要求对没有 platformId 的主体跳过因为可见性对他们本来就无效。关键细节跳过空字符串projectId不只 nilisNil()为 false空串会流到projectService.getOneOrThrow()造成 404。而 Web 端qs.stringify会把 null 的projectId序列化成projectId——所以调用处必须传getProjectId() ?? undefined绝不能传getProjectId()!版本门槛该断言是 EE/Cloud 专属。在 CE 上projectId只会到达resolveVisibility不会进入 search/sort 路径参数无效若在 CE 上做无门控的成员检查只会把原本正常的 200 变成 403/404残留的信息泄露面EE/Cloud 上不存在的或已软删除的项目 id 返回 404而真实存在但你非成员的项目返回 403——对任何已认证用户而言这是一个项目存在性预言机project-existence oracle。各类主体实际获得的结果文档给出了在三个版本、三条路由上实测一致的主体行为矩阵主体行为项目成员任意角色含 VIEWER可读取自己的项目访问兄弟项目被 403 拒绝平台 ADMIN / OPERATOR通过隐式角色projectMemberService.getRole可读取本平台每个项目SERVICE api key可读取自己平台的所有项目被拒绝访问其他平台WORKER / UNKNOWN / 未认证被跳过、不泄露任何信息——带任何projectId都返回未过滤的平台目录resolveVisibility因 platformId 为 nil 直接短路因此也永远收不到过滤被集隐藏的 Piece 对他们仍可见ONBOARDING在认证阶段就 401INVALID_BEARER根本到不了这些处理器getPlatformId的 ONBOARDING 分支在此是死代码ENGINE只被允许自己的projectId该分支直接比较 id、不做查询不存在的 id 也被拒绝目前没有调用方这么做但对第一个尝试者是陷阱由于守卫让这些路由可能失败任何把用户可控projectId放到这些路由上的界面都必须呈现拒绝结果。文档特别指出 Reach tab 目前尚未做到?project不可读时返回 403未知 id 返回 404页面会渲染 No pieces are reachable in this project. 空状态且无错误提示被误读为该项目没有 Piece而非你没有访问权限已在真实 EE 服务器上验证非过期 bundle 或缺失showErrorDialog。Embed 令牌的 pieceSet claimEmbed 认证中v4 JWT携带pieceSetkey claim直接对应命名集key tag映射遗留 v2/v3 令牌携带piecesTags只认第一个 tag解析为key tag找不到则回退 Default。执行逻辑在 managed-authn-service.ts 的applyProjectPieceAccess取pieceSetKey ?? (piecesFilterType ALLOWED ? piecesTags[0] : undefined)按 key 查命名集命中则assignProject未命中key 存在但找不到记录 warn 日志并回退默认集。Embed 租户相互隔离通过POST /v1/managed-authn/external-token铸造的令牌只能读自己的项目访问兄弟项目或其他 embed 用户的项目均 403。该端点也是测试中获取真实 embed 主体的便捷方式无需手搓。前端实现Web 端代码位于 packages/web/src/features/piece-sets/管理界面位于 packages/web/src/app/routes/platform/setup/pieces/piece-sets/tabs 与对话框。piece-sets-hooks.ts 提供pieceSetQueriesusePieceSets/usePieceSet与pieceSetMutations创建、更新、删除、复制、批量分配、移除、批量移除每个 mutation 成功后会失效相关查询键并调用pieceCacheUtils.invalidatePieceCaches(queryClient)与projectCollectionUtils.refetchProjects()——因为可见性是读取时派生的更新集之后必须让 Piece 缓存失效下一次列出才会重新解析分配/移除项目后还会失效[projects-for-platforms]查询保证项目选择器同步。常见陷阱usePieces 的 skipProjectFilterusePieces({ skipProjectFilter: true })不是缓存开关——它会静默关闭 Piece Set 过滤它从GET /v1/pieces请求中去掉projectIdresolveVisibility只要platformId或projectId任一为 nil 就短路返回null于是响应变成未过滤的平台目录。platformId仍来自主体所以这不是租户隔离漏洞但任何使用它的界面都会向用户展示受限项目实际不会暴露的 Piece影响 flows 与 MCP server 的可见性。在平台管理员界面Piece Set 编辑器必须列出尚未允许的 Piece和营销式展示场景使用它是正确的在列表暗示当前环境可用范围的任何地方使用它都是错的。调用点容易漏看因为该 flag 读起来像客户端关注点。镜像陷阱flag 关闭时usePieces会作用域到authenticationSession.getProjectId()——即会话所在项目。因此平台管理员界面在检查其他项目时如带项目选择器的 MCP Reach tab必须显式传projectId否则会静默地在别的项目名下渲染管理员自己项目的 Piece。数据迁移三步有序推进迁移必须按序执行三步建表 回填1807...创建piece_set表并用原生 SQL 一次性读取遗留tag/piece_tag表进行回填并发索引1808...CREATE INDEX CONCURRENTLY非事务性删除遗留列1809...破坏性移除遗留的 platform piece-filter 列。遗留tag/piece_tag表仅因回填需要保留只读一次回填完成后不再使用。关键文件索引入口与业务逻辑piece-set.service.ts、piece-set.controller.ts、piece-set.entity.ts、piece-set.module.ts、piece-set-config.ts目录packages/server/api/src/app/ee/pieces/piece-set/共享模型与纯解析器packages/core/shared/src/lib/ee/piece-set/index.ts读取时过滤应用piece-filtering-utils.tsEmbed 令牌强制managed-authn-service.ts新项目默认集分配ee-project-hooks.ts前端 hooks 与 APIpackages/web/src/features/piece-sets/管理 UIpackages/web/src/app/routes/platform/setup/pieces/piece-sets/设计决策ADR 000007Piece-set visibility is derived at read time小结Piece Sets 通过具名集 读取时派生 声明式更新的组合为多租户平台提供了一套可扩展、免安装时写扩散的 Piece 可见性治理方案。理解include_all/exclude_all双模式、组件层的精选语义、Default Set 兜底、managePiecesEnabled门控边界以及projectId参数的主体权限矩阵是正确使用与安全接入该功能的关键而skipProjectFilter等调用陷阱则提醒我们在任何暗示可见范围的界面上都要谨慎选择过滤参数。【免费下载链接】activepiecesAI Agents MCPs AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepieces创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。