Canvas 资源模型
CanvasDocument、CanvasRevision、节点、Binding 与执行快照的领域边界
Canvas 资源模型
本文定义 Canvas 产品侧需要落地的资源语义。统一 Resource Envelope、Project 外壳、Asset Graph、Run 和领域事件的权威规范仍在共享内核;本文只说明 Canvas 如何使用它们。
已确认边界
Project是 Organization / Workspace 下的跨产品业务目标容器。CanvasDocument是无限画布的稳定业务身份,不是 Project 的别名。CanvasRevision是可执行、可分享、可交接的不可变版本。- 正式媒体由 Asset Service 以 Asset / AssetVersion 管理,Canvas 只保存稳定引用。
- Agent、Model Offering、Run、MCP Connection 和 Billing Account 各有自己的事实源。
- Console 管理全局资源;Canvas 只写 Canvas 领域拥有的数据并提供上下文视图。
当前态
当前代码以 CanvasProject 表达一张画布,聚合节点、连接、视口、聊天和部分执行状态,并主要按当前用户归属。这个实现支持现有编辑器,但名称与边界存在三个问题:
- 它容易与目标架构中的跨产品
Project混淆。 - 可变画布状态、可复现执行版本和运行状态尚未形成清晰的独立身份。
- 媒体 URL、生成任务和画布节点之间的关系还需要收敛为稳定资源版本引用。
当前 CanvasProject 因此视为 CanvasDocument 的迁移前实现,不应继续扩展为漫剧、电商或 Developer App 的通用容器。
目标态:资源聚合
Project(共享业务目标,可选关联)
└── CanvasDocument(稳定身份)
├── currentRevisionId
├── CanvasRevision[](不可变)
│ ├── Node[]
│ ├── Edge[]
│ ├── ResourceBinding[]
│ └── ExecutionSnapshot[]
└── 协作、权限和生命周期元数据CanvasDocument 使用共享 Resource Envelope,因此至少具备 organizationId、workspaceId、可选 projectId、所有者、当前版本和数据分类。领域 Payload 由 Canvas 域保存,Resource Registry 不复制完整节点图。
CanvasDocument
CanvasDocument 负责稳定身份与生命周期:
- 标题、说明、状态与当前 Revision 指针;
- 所属 Organization / Workspace 与可选 Project 关联;
- 创建者、负责人、协作者和分享策略;
- 模板来源、分叉来源和产品来源摘要;
- 删除、归档和保留状态。
Document 本身不保存“运行中的最新上游结果”作为可变事实,也不拥有被引用 Asset、Agent、模型或外部 Connection。
CanvasRevision
CanvasRevision 是某一时刻画布的不可变快照,至少固定:
- 节点、连接、分组、布局和必要视图状态;
- ResourceBinding 指向的明确资源版本;
- 本版本的父 Revision 与创建原因;
- 创建者、时间、Schema 版本与内容摘要;
- 可复现执行所需、但不包含 Secret 的配置引用。
编辑期间可以维护可变工作副本或增量操作日志;当画布被执行、分享、发布、Handoff 或写回产品时,必须先固化为 CanvasRevision。已经被 Run 或其他资源引用的 Revision 不得原地修改。
Node 与 Edge
Node 保存 Canvas 自己拥有的可视表达和编排语义,例如内容节点、资源引用节点、Agent 节点、生成节点、控制节点与产品扩展节点。Edge 表达数据流、依赖或视觉关系。
约束如下:
- Node Payload 只保存当前节点所需的 Canvas 配置,不复制完整 Asset、Agent 或产品对象;
- 媒体内容通过 ResourceBinding 引用 AssetVersion,URL 只作为短期展示结果;
- 模型节点引用公开 Model Offering 或逻辑策略,不保存 Provider、Channel、Supply 或 Credential;
- MCP 节点引用获授权的 Connection / Tool Grant 摘要,不保存 Token 或 Secret;
- 漫剧和电商专属节点使用 Product Node Namespace,其正式业务状态仍由来源产品维护;
- Edge 不能被当成跨领域写权限,产品写回仍需显式命令。
ResourceBinding
ResourceBinding 把画布节点连接到外部稳定资源,解决“这张图来自哪里、固定哪个版本、可以做什么、结果回到哪里”。
Canvas 侧最小语义包括:
| 语义 | 说明 |
|---|---|
bindingId | 稳定 Binding 身份 |
nodeId | 当前 Revision 中承载引用的节点 |
resourceId | 被引用资源的稳定身份 |
resourceRevisionId | 固定版本;正式执行不能仅跟随 current |
relation | used_in、derived_from、bound_to 等受控关系 |
sourceProduct | 资源事实源所在产品 |
bindingRole | 输入、输出、上下文或来源等 Canvas 内角色 |
Asset 可以使用 assetId / assetVersionId 的专用引用表达,但仍遵守相同固定版本规则。Binding 不复制源对象 Payload,也不把签名 URL、标题或提示词当作身份,更不能代替实时授权判断。
跨产品返回目标由 Handoff 的 returnBinding 表达,它可以引用来源资源和业务槽位,但不属于普通 ResourceBinding 的授权字段。
绑定模式
| 模式 | 行为 | 适用场景 |
|---|---|---|
| 固定引用 | 使用指定 Revision,源更新不自动改变画布 | Run、Handoff、审核和发布 |
| 显式升级 | 用户查看差异后把 Binding 更新到新 Revision | 上游素材迭代 |
| 派生 | 从固定版本生成新资源并保留血缘 | 编辑、生成和变体 |
| 复制 / 分叉 | 在授权后创建新所有权资源 | 跨 Workspace 使用 |
“始终跟随最新版”只能用于非执行性的浏览提示,不能进入 Execution Manifest。
ExecutionSnapshot
ExecutionSnapshot 是 CanvasRevision 与统一 Run 之间的可追溯连接,不是第二套任务状态机。它记录:
runId、触发节点和输入 CanvasRevision;- 固定的输入 Resource / Asset Version;
- 使用的 Agent Revision、Model Offering 与 Tool Version 引用;
- 输出资源和对应节点 Binding;
- 用户可见状态摘要、创建时间和
traceId。
实时状态、Step、Attempt、审批、取消、重试、用量与结算由 Run Service 管理。Canvas 可以缓存可重建摘要,但不能用本地快照反向覆盖 Run 状态。
Provider 账号、物理上游模型 ID、Gateway Credential、内部基础提示词和详细路由策略不得进入 CanvasRevision 或 ExecutionSnapshot。
资源与服务所有权
| 对象 | Source of Truth | Canvas 可以做什么 | Canvas 不得做什么 |
|---|---|---|---|
| CanvasDocument / Revision | Canvas 域 | 创建、编辑、固化版本、授权协作 | 伪装成全局 Project |
| Asset / AssetVersion | Asset Service | 上传、引用、派生、请求删除影响分析 | 以 URL 代替身份或直接删除 Blob |
| Agent / Agent Revision | Agent Registry | 选择获授权版本并创建 Run | 修改私有定义或扩展运行权限 |
| Run / Step / Attempt | Run Service | 创建、订阅、取消或按契约重试 | 在 Canvas 中伪造终态 |
| Model Offering | Model Control | 使用 web Surface 的适配能力 | 读取或写入 Provider / Channel |
| Connection / Tool Grant | MCP 域 | 展示授权摘要并请求工具调用 | 读取 Credential 或 Secret |
| Wallet / Billing Account | Billing 域 | 展示预估、预占和结算摘要 | 修改余额、账本或付款主体 |
| Project / Membership | Tenant / Identity 域 | 绑定当前上下文 | 创建第二套全局层级 |
| Drama / Commerce 对象 | 对应产品域 | 固定版本引用并返回候选 | 直接修改 Shot、SKU 或发布状态 |
编辑、执行与版本生命周期
规则:
- Run 总是读取已经固定的 CanvasRevision 和 AssetVersion。
- 运行期间继续编辑只影响新的工作副本,不改变已启动 Run。
- 生成多份结果时全部登记为候选 AssetVersion;选择主结果只改变 Binding。
- 重试创建新的 Attempt,并保留原 Attempt、结果和费用事实。
- 将结果放回画布会形成新的 Revision,不回写历史 Revision。
- 公开分享或产品写回固定明确版本,不能依赖“打开时最新”。
组织、权限与归属
- 个人空间中的 Document 归个人 Workspace;企业 Workspace 中创建的 Document 归企业。
createdBy记录创建事实,不改变资源所有权。projectId是业务关联,可为空,不替代 Workspace 所有权边界。- 分享 Document 不自动分享其引用的受限 Asset、Agent 内部定义或 MCP Credential。
- 用户访问某个 Revision 时,服务端必须同时验证 Document 权限和每个外部 Binding 的可见性。
- 跨 Workspace 默认通过复制、分叉或显式授权,不在浏览器中偷偷复用源权限。
- 成员离职后企业 Document 与 Revision 原地保留,新 Run 按最新 Membership 和授权重新校验。
删除与保留
删除 CanvasDocument 前必须执行引用影响分析:
- 被 Handoff、Run、发布作品或其他产品资源引用的 Revision 保留可审计关系;
- 删除 Document 不等于删除其引用的 AssetVersion;
- 仅由该 Document 产生但仍被其他对象引用的输出不得回收 Blob;
- 用户界面明确选择删除时,Canvas 域删除自己的聚合,不以归档冒充删除;
- 法定保留、审计和账本记录由对应领域按策略保存,不能由 Canvas 级联清除。
从当前态迁移
| 当前语义 | 目标语义 | 迁移要求 |
|---|---|---|
CanvasProject | CanvasDocument | 改名并与共享 Project 分离 |
| 用户级归属 | Organization / Workspace / 可选 Project | 所有读写显式解析上下文 |
| 可变整体快照 | 工作副本 + 不可变 CanvasRevision | 执行、分享和交接固定版本 |
| 节点内媒体 URL | AssetVersion Binding | URL 仅用于短期呈现 |
| 节点内任务状态 | ExecutionSnapshot + Run 引用 | Run Service 成为状态事实源 |
| 直接产品字段 | Product Node + ResourceBinding | 来源产品保持领域所有权 |
项目尚未正式上线,实施时应按目标模型直接调整数据结构,不为错误命名增加旧字段兼容;需要保留的开发测试夹具按新模型重建。
目标态验收
- 代码、API 和界面可以清楚区分共享 Project 与 CanvasDocument。
- 任意被执行、分享、发布或 Handoff 的画布都能解析到不可变 CanvasRevision。
- 节点引用的媒体、Agent 和产品对象均使用稳定资源版本 ID,刷新或签名 URL 过期不丢失关系。
- 同一 Revision 重放能够还原固定输入、Agent、模型策略、工具版本和输出血缘,但不会暴露 Secret。
- Canvas 运行状态来自统一 Run;失败重试形成新 Attempt,不覆盖旧事实。
- 生成多结果时每个成功结果都登记为 AssetVersion,主结果选择不删除其他候选。
- Console 与 Canvas 对同一 Document / Asset 的归属、权限和版本结果一致。
- Canvas 不能通过节点 Payload 或 Binding 绕过权限直接修改 Shot、SKU、钱包、Provider 或 MCP Credential。
- 删除 Document 前能列出有效引用,且不会留下静默失效的 Asset 或产品 Binding。