无限画布无限画布

数据库结构

主画布的本地 PostgreSQL 隔离规则

数据库结构

Partner 自动换头路由记录

复用 app_state 表,键前缀为 partner-head-route:,后缀是用户 ID 与幂等操作 ID 的 SHA256。JSON 记录双方图片及有效 prompt/seed 的请求指纹、实际模型、路由依据、检测版本和权重哈希。首次插入固定路由;重试不覆盖,输入变化返回 409。仅鉴权后的服务端代码访问,不存图片原文或密钥。回滚应用时保留记录,避免历史任务重试切换模型。没有新增或删除表。

Agent 步骤尝试标识(候选)

20260905_agent_plan_step_attempts.sql 新增 agent_plan_step_attempts。主键为(snapshot_id, step_id, attempt),operation_id全局唯一;记录输入SHA256和Skill历史版本,外键关联计划快照与user_skill_versions。身份字段不可更新;快照删除时级联清理。非空表拒绝down,回滚必须先处理依赖并保留已有记录。

该表不是执行状态机;尚未接入步骤归属校验、Skill执行引用事务、归档引用审计、审批、事件和Worker下发。不得独立开放写入或将存在记录视为允许重试。当前验证使用隔离schema的最小父表,完整关系与账户删除行为仍待集成验证。

Agent 计划快照基础(候选)

20260905_agent_plan_snapshots.sql 新增 agent_plan_snapshots:id、owner_user_id、project_id、plan_id、plan_revision、snapshot(JSONB)、created_at。所有者/画布/计划/修订唯一,UPDATE由触发器拒绝。用户删除级联清理,画布ID保留历史来源,不设画布删除级联。服务端准入必须另行检查当前成员权限。

此表目前仅为不可变提案输入基础,已有受鉴权快照读写API;仍无步骤尝试、执行授权、Skill锁定或预算审批;不能据表存在认定执行闭环完成。down迁移持排他锁后拒绝删除非空表;仅空表允许回滚,已有快照应保留而非清空。

隔离规则

  • 主画布只允许连接本机或 Compose 内的 postgres 服务,数据库名固定为 infinite_canvas。
  • 本地 Docker 编排不发布 PostgreSQL 端口。根 Compose 的项目名是 infinite-canvas,数据卷是 infinite-canvas_postgres_data;docker-compose.local.yml 使用独立的 infinite-canvas-local_postgres_data。
  • 历史 deploy 入口必须继续使用项目名 infinite_canvas、数据库凭据契约和显式 external volume infinite_canvas_postgres_data。卷缺失时部署应失败关闭,不能创建空数据库掩盖问题。
  • Compose 不再设置全局 container_name,容器和网络仍按 infinite-canvas、infinite-canvas-local、infinite_canvas(历史 deploy)或 infinite-canvas-prod 项目域隔离。
  • 主画布发现远程数据库主机、其他数据库名或缺失 DATABASE_URL 时会拒绝建立连接。
  • 本地与部署 Compose 均使用自身 PostgreSQL 服务和项目命名卷,数据库不发布宿主机端口;Web 通过 Compose 服务名 postgres 连接,禁止连接宿主机现有 PostgreSQL。
  • 当前目录部署的生成媒体与任务参考文件分别限制在 Justin spicy-cc 的 infinite-canvas/media 和 persona-video 前缀,不复用其他项目的对象前缀。
  • 部署内置的模型供应商与 OSS Key 仍只从本项目环境文件读取;管理员新增的模型供应商密钥使用 AUTH_SECRET 派生的 AES-256-GCM 密钥加密后写入本项目 PostgreSQL,禁止从其他项目数据库读取或复用密钥。
  • 切换 Compose 入口前先用 docker compose -f <文件> config --volumes 和 docker volume inspect <卷名> 核对目标;项目不自动迁移或复制卷,禁止对任何保留数据的入口执行 down -v。

主画布表

模型供应商凭据

表说明
ai_provider_credentials管理员新增的供应商、API 地址、模型目录、启停状态及 AES-256-GCM 加密密钥;不保存明文密钥
ai_provider_credential_audit创建、更新、删除以及显示完整密钥的管理员审计记录

部署环境中的现有供应商配置以只读条目展示。完整密钥接口要求管理员会话、禁用响应缓存,并记录显示动作;浏览器仅在管理员主动显示后的 30 秒内保留明文。

app_state

保存画布、素材与操作日志等 JSON 状态。“我的素材”图片在素材 data.md5 中保存按原始字节分块计算的 MD5,用于同一用户素材列表去重;新增或替换图片缺少有效摘要时服务端拒绝写入,未更换媒体内容的历史素材仍允许缺少该字段。

字段类型说明
keyTEXT主键,区分画布、素材和日志域
dataJSONB业务状态
updated_atTIMESTAMPTZ更新时间

media_objects

保存生成图片、视频等媒体的对象存储元数据;媒体本体保存在项目配置的 OSS 前缀下。

字段类型说明
storage_keyTEXT主键,前端媒体标识
oss_keyTEXT唯一的 OSS 对象键
mime_typeTEXT媒体类型
bytesBIGINT文件大小
sha256TEXT内容摘要
created_atTIMESTAMPTZ创建时间

多人画布协同

迁移 20260821_canvas_collaboration.sql 将画布从用户级 user_app_state JSON 镜像为独立项目资源;旧数据仍保留并由兼容接口同步,迁移不删除旧字段。

表说明
canvas_projects独立画布文档、所有者、当前 revision 与更新时间
canvas_project_members项目成员,角色为 owner/editor/viewer
canvas_project_operations按项目单调 revision 保存节点、连线增删改操作,operation_id 保证重放幂等;新节点修改使用 JSON Pointer 字段 Patch,节点文档内的 __collaboration.version/fields 记录节点及字段最近 revision,用于合并不同字段并拒绝同字段旧版本写入
canvas_project_user_history按画布和用户保存个人 undo/redo revision 栈;每条操作同时保存字段级 inverse_operations,刷新后仍可只撤销自己的操作,并让重做沿原 revision 恢复;指定历史版本恢复会反向重放操作并追加一条 action_kind=restore 的新 revision,不改写或删除旧历史
canvas_project_presence兼容旧版本的 Presence 表;新版本不再持续写入,光标、选区、编辑/拖动软锁改存 Redis 20 秒 TTL 键,PostgreSQL 仅保存持久画布内容和操作历史
canvas_project_comments画布级或节点锚点评论、回复、图片附件、软删除以及解决状态;节点删除后评论仍保留
canvas_project_comment_reads每位成员在每张共享画布上的评论最后已读时间,用于未读提醒
canvas_agent_histories按用户、画布、Agent 模型和线程保存 Canvas Agent 对话;PostgreSQL 为刷新及跨设备恢复真源,IndexedDB 保留离线缓存
canvas_project_invites只保存一次性邀请 token 的 SHA-256,支持角色、过期、使用人与使用时间以及 Owner 主动吊销;明文链接只在创建响应中出现一次
canvas_project_media_refs画布引用的媒体对象;项目成员可读取引用媒体,但写入和对象所有权仍归原上传者
opencut_sessions画布到 OpenCut 的短期编辑会话;保存项目、操作者、选中节点、状态和过期时间,只保存一次性 token 的 SHA-256,不保存媒体正文或明文凭据

OpenCut 会话只允许 owner/editor 创建,默认 15 分钟过期。服务端从当前持久画布文档重新解析选中媒体,拒绝浏览器伪造的节点地址;导回成片时先写入当前用户的 media_objects,再以该操作者身份追加 node.upsert 协同操作并把会话标记为 exported,因此新视频节点会进入画布 revision、个人撤销栈、媒体引用和 SSE 同步。后续继续补单编辑者锁和管理员审计。

Priya Live 发布快照

迁移 20260831_priya_live_releases.sql 建立三张发布表:

表说明
priya_live_releases保存 root 显式批准的 source manifest v2、canonical JSON、SHA-256、来源画布 revision、目标角色与上一 release;actor_user_id + idempotency_key 唯一
priya_live_release_assets按 release 冻结画布 node、槽位、业务配置、storage_key、owner、OSS key、MIME、字节数和 SHA-256;manifest 与浏览器响应不会暴露 OSS key
priya_live_outbox保存同事务创建的 priya_live.release.published 原始事件正文、event ID、attempt、lease、退避时间和脱敏回执

发布服务只以 identity_bootstrap.user_id 判断站点初始管理员,不按可变用户名授权。素材必须来自服务端重读的持久画布,且当前操作者是 owner/editor,并拥有媒体或通过 canvas_project_media_refs 获得项目共享读取权。media_objects_reject_priya_live_frozen_repair 触发器会阻止修改任何已进入 release 的 OSS key、MIME、字节数或 SHA-256;后续修复必须产生新的 storage_key 和 release。

Outbox 使用 FOR UPDATE SKIP LOCKED、30 秒 lease 和带抖动的指数退避;连续 12 次失败进入 dead,人工 retry 会将同一 event ID 重新置为 pending。常驻 priya-live-outbox-worker 仅连接 PostgreSQL 并持有 webhook HMAC 配置,不挂载媒体目录。

浏览器直传 reservation

迁移 20260831_direct_media_upload_reservations.sql 建立 direct_media_upload_reservations。每次 ticket 都生成新的 reservation UUID 与 direct-stage:<date>_<uuid>;浏览器仅向映射后的唯一 direct-immutable OSS key 流式上传,OSS create-only 条件写保证同一 ticket 的并发或重放不会覆盖先到字节。finalize 在 media-object:<storageKey> advisory transaction lock 下校验 reservation、owner、MIME、字节数和 SHA-256,然后直接插入 media_objects 并标记 committed;成功响应丢失时,同一签名 receipt 与 committed 行完全一致即可幂等返回。

direct-media-cleanup-worker 使用 FOR UPDATE SKIP LOCKED 领取到期的 pending/expired reservation,只删除其数据库记录指向的 staging key;committed 行永不进入清理查询。Proxy 删除前等待同 staging key 的在途 OSS 上传结束,避免先删后写造成孤儿。回滚不修改 media_objects 数据;只要仍有未 cleaned 的 pending/expired reservation,down migration 会 fail closed,必须先让 cleanup worker drain 完成。Priya Live down migration 同样会在任意 release、asset 或 outbox 业务行存在时中止,避免丢失不可变发布证据;须先完成导出/归档流程,不能把 down 当作数据清理命令。

个人 Skill:user_skills

迁移 20260826_user_skills.sql 新增按用户隔离的个人 Skill 表。PostgreSQL 是个人 Skill 在刷新和跨设备恢复时的唯一持久化真源。

字段类型说明
idUUIDSkill 主键
owner_user_idUUID所有者,关联 users;用户删除时级联删除其 Skill
source_project_idTEXT可选来源画布,关联 canvas_projects;来源画布删除时置空,不删除 Skill
source_kindTEXTconversation、workflow、combined 或 manual
name / summary / categoryTEXT名称、摘要和分类,均有长度约束
tagsJSONB标签数组
manifestJSONB版本化的可复用指令、触发词、输入定义,以及可选的净化工作流模板
source_refJSONB只保存允许的来源项目、会话、消息、节点和 revision 标识,不保存完整对话或媒体
revisionBIGINT从 1 开始的乐观并发版本;更新和归档均校验预期 revision 并递增
archived_atTIMESTAMPTZ软归档时间;普通列表只返回未归档记录
created_at / updated_atTIMESTAMPTZ创建及最近更新时间

Skill 草稿在 Web 服务内使用确定性规则生成,不调用外部 AI 服务。对话来源只读取当前登录用户在当前画布已持久化的最近用户/助手文字,忽略媒体附件;工作流来源只从用户有权读取的持久画布文档提取最多 30 个节点、相对位置和内部连线;组合来源同时生成指令和工作流模板。

工作流模板采用字段白名单:保留提示词、模型、生成参数、文本内容及内部结构,移除媒体内容、对象存储键、临时或签名地址、任务标识、生成状态与耗时,并对类似 API Key、token、secret 的文本做脱敏。节点、连线、组、批次、mention 和 references 在保存及实例化时只允许模板内部引用,复用时全部换成新的实例 ID。助手 Skill 复用时只填入指令;工作流 Skill 复用时只新增节点和内部连线,不自动触发生成。

所有查询、创建、修改和归档均按 owner_user_id 约束,成功响应使用 private, no-store。创建带来源画布的 Skill 前还会校验成员身份;修改使用 expectedRevision 比较并交换,陈旧 revision 返回冲突;归档只设置 archived_at,不会物理删除历史记录。

协同写入会锁定 canvas_projects 行、应用一批实体级操作、递增 revision,并在同一事务中写入操作记录和刷新媒体引用。不同节点的并发修改不会因为整份项目 JSON 覆盖而互相丢失;同一节点的并发修改按服务端接收顺序收敛。浏览器通过 after=<revision> 拉取缺失操作,单页超过 500 条时继续分页,不跳过中间 revision。

评论不写入画布 document,也不占用画布 revision。图片评论的媒体本体保存在 OSS,attachment_storage_key 只保存媒体引用;画布成员通过评论与成员关系读取附件。创建、回复、编辑、软删除和解决/重开评论后,通过同一 PostgreSQL LISTEN/NOTIFY 与鉴权 SSE 通知在线成员刷新评论;viewer 可以评论和管理自己的评论,editor/owner 可以解决讨论,owner 还可以删除项目内评论。

Video Dataset Engine schema

VDE 使用独立的 video_dataset schema,不与主画布的媒体任务表混用。processing_job 是异步处理的权威状态:Redis/RQ 只负责投递,不能替代 PostgreSQL 记录。

本阶段为 processing_job 增加以下字段:

字段类型说明
cancel_requestedBOOLEAN持久取消意图;终态取消同时清除 lease
claimed_byVARCHAR当前 worker 所有者,用于写入 fencing
lease_expires_atTIMESTAMPTZlease 截止时间;过期任务由恢复循环重试或终结
heartbeat_atTIMESTAMPTZ最近一次成功续租时间
available_atTIMESTAMPTZ退避重试的最早可投递时间

查询索引覆盖 dispatch(status/available_at/priority/created_at)、过期 lease(status/lease_expires_at)和目标幂等查找(job_type/target_type/target_id)。升级时旧 running 记录会立即过期,由新 worker 的恢复循环接管,不创建无所有者的未来 lease。

清洗、标注与审核结果不写入 shot JSON,而是保存在独立、可追踪的记录中:

表说明
overlay_detection字幕、水印、Logo 等覆盖物的时间段、区域、置信度与检测器版本
quality_measurement按技术、美学、运动等分组保存可解释指标与评估器版本
caption_annotation按 caption 类型保存不可变修订、模型、prompt 版本和人工 actor
review_decision保存批准、拒绝或退回的不可变人工决策历史

Caption 和审核 revision 通过锁定所属 Clip/Shot 后顺序分配。审核决策与 shot.review_status 在同一事务中更新;Caption 变更会使已有批准回到 needs_review。

分析写入保存 clip_revision,并同时校验当前 Clip revision、未退役 Shot、未软删除 Asset、同 Asset Variant,以及仍由当前 Worker 持有的 Processing Job lease。Overlay 与质量结果通过 (processing_job_id, detection_index/shot_id/metric_group) 幂等,Processing Job 与 Shot 的复合外键阻止跨目标结果。迁移会为旧分析行创建已完成的 provenance job,按结果时间保守回填 revision,并把非 object 的旧 JSON 包装到 _legacy_value,不静默丢弃历史值。

Shot merge 不再物理删除右侧 Shot,而是将其标记为 retired_at 并从活动时间线过滤,因此旧 Caption、检测、质量和审核历史仍可追溯。已被分析记录引用的媒体 Variant 不允许删除。

shot_analysis durable job 会先在源 Variant 上按 Shot 时间段抽样,保存字幕、水印、Logo、黑边检测以及技术/运动指标。检测到覆盖物时,Worker 使用 FFmpeg delogo/crop 生成以 SHA-256 定址的不可变 clean Variant,再对清洁结果重新测量并生成 Visual/Motion Caption;未检测到覆盖物时直接复用源 Variant,不产生空清洗副本。所有结果与 job 完成状态在同一数据库事务写入,并保存 detector、assessor、caption model、prompt、processor 及其版本。素材读取、OpenCV 和 FFmpeg 阶段持续检查 PostgreSQL lease 与取消状态;超时采用 durable retry,Clip revision 变化则拒绝陈旧结果。

人工审核 API 聚合当前 Shot 的 Variant、覆盖物、分项指标、Caption 修订和 review history。人工 Caption 与 decision 都要求 operation ID、当前 Clip revision 和预期 revision;review 还绑定各 Caption 的最新 revision,因此重复提交幂等,并发修改返回冲突而不会覆盖。Variant 内容通过受服务鉴权保护的流式接口读取,支持单段 HTTP Range,Next.js BFF 只转发白名单路径和必要的媒体响应头。

生成详情审计

generation_details 以 operation_id 一对一关联 credit_reservations.operation_id,记录管理后台生成详情:

  • prompt:最多 20,000 字符的生成提示词;
  • request_details:能力、规范化模型以及尺寸、时长、帧率、数量等允许的标量参数;生成提交取得 claim 后记录经画布权限校验的 canvasProjectId(无画布为 null)。重复提交或恢复不回填来源,旧记录缺失此字段表示未知,不能推断为当前画布;此字段不是 Agent 步骤或产物真实性证明。可选 generationOrigin 保存客户端提交的 run/request/canvas/attempt/sourceNode/outputNode 标识;经字段与当前授权画布校验,不代表已验证本地 Agent 日志或产物,禁止据此直接恢复执行。
  • result_details:供应商任务状态、错误以及图片/视频结果地址;
  • created_at / updated_at:首次记录和最近一次轮询更新时间。

该表不保存输入媒体二进制、Data URL、Cookie、Token 或供应商密钥;历史计费记录不会反向补写提示词。

模型积分报价

credit_prices 同时保存能力通配价与模型精确价。迁移 20260907_model_price_coverage.sql 为计费策略当前接受的 185 个“能力 + 规范模型”组合写入精确报价:每项从生产中对应能力的当前通配规则继承单位、积分和启用状态。写入使用 ON CONFLICT DO NOTHING,因此管理员已经调整的精确价格保持不变;通配价继续作为后来新增模型的兜底。

运行时初始化会执行同一份精确定价策略,新增到服务端计费白名单的模型会自动获得可编辑报价。模型别名先规范到实际执行模型再计费,不为同一执行链重复建立价格。credit_price_seed_rows 只登记迁移实际新增的行;回滚还会核对创建与更新时间未变化,只删除从未被管理员修改的本批默认行,不删除迁移前精确价、通配价或管理员定价。

Skill 版本快照(开发候选)

user_skill_versions 以 (skill_id, revision) 为主键,保存 snapshot JSONB 与 created_at。Skill 插入或 revision 递增更新在原事务内由触发器保存快照,直接 UPDATE 快照被拒绝。迁移仅回填当前行,不重建未知历史。无执行引用时,Skill 删除沿原用户数据删除语义级联删除快照;存在执行引用时受下述外键保护。冷归档仍未实现。历史读取 API 必须关联 user_skills 校验所属用户,不直接暴露快照。

迁移 20260905_user_skill_versions.sql 可重复执行;对应 rollback 只停用捕获触发器并移除迁移标记,保留表与历史。回滚窗口新增修订不会被捕获,再升级只能回填当时当前版本。此候选尚未应用生产。

Skill 执行引用保护(开发候选)

user_skill_execution_refs 以 (owner_user_id, execution_id, skill_id) 为主键,固定 revision,并通过延迟外键引用版本快照。引用存在时删除版本或 Skill 会被阻止;删除画布只清空 project_id,保留引用,删除账户沿所属关系清理。新增 pin 服务在写入前校验 Skill 所属用户和画布成员关系,同一执行改绑不同版本或画布返回冲突。开发候选已接入本机与网站 Agent、普通工作流生成与重试;尚未发布,不能宣称线上运行已被保护。后续冷归档必须检查该表,并保留被引用快照。

来源画布删除触发 user_skills.source_project_id 的外键 SET NULL 时,仅在其余字段完全相同且原画布已不存在的情况下跳过快照捕获。此操作不递增内容版本,历史快照保留原始来源;手动清空仍存在的来源画布关联仍需递增 revision。真实隔离数据库已验证画布删除、历史保留、执行引用保留和手动绕过拒绝。

Skill 归档对象定位(开发候选)

user_skill_archive_locations 以 (skill_id, revision) 关联版本快照,保存 sha256(64 位小写十六进制)、bytes(1–16 MiB)和 verified_at。对象键由授权查询所得 owner、skill、revision 与摘要构造,不保存外部 URL 或凭据。历史读取与执行引用读取经既有用户/成员校验后,有定位记录则通过私有 Proxy 读取并校验;失败直接报错,不回退最新版或掩盖损坏。

迁移 20260905_user_skill_archive_locations.sql 已加入平台迁移列表,必须先迁移再部署读取代码。定位登记服务已实现;冷快照迁移及释放服务见下节,仍无自动维护入口。只在期限、引用及并发校验通过、实际上传回读一致后登记。启用冷快照后必须先回填所有冷版本再回滚架构,禁止先删除定位表。

registerSkillColdArchive 是内部维护服务:明确 cutoff,事务外上传回读;事务内对执行引用表持 SHARE 锁、对版本和当前 Skill 行加锁,再核对资格和内容摘要。锁等待上限 5 秒,单条语句上限 15 秒,锁内无 OSS 网络调用;相同定位幂等,不同定位拒绝覆盖。该锁会短暂影响全部执行引用写入,实际引用阻塞与释放后可写已通过隔离 PG 验证;完整登记事务/HTTP/OSS 联合验收已通过;业务延迟和维护入口仍须验证后才能开放批处理;实际释放由独立 evict 服务执行,见下节。

restoreSkillArchiveHotCopy 用于仍保留热快照的阶段:先校验用户归属和归档实际字节,再在版本行锁下比较当前定位与热快照摘要,一致才删除定位,恢复本地读取。重复恢复不写数据;失败保留定位。此操作不删除 OSS 或执行引用;冷快照迁移启用后也支持从 OSS 校验内容回填,受数据库原内容摘要约束。

Skill 冷快照释放与回填(开发候选)

20260905_user_skill_cold_snapshots.sql 将 snapshot 改为可空并新增 content_sha256。该摘要由 PostgreSQL 对原 JSONB 文本计算 SHA-256,与 OSS 对象字节摘要不同,专供回填不可变性验证。新版本插入仍必须包含快照;已有版本仅允许通过受限转换从非空到空、或从空回填摘要匹配的原内容。身份、revision、created_at 等字段保持不可变。

释放服务先实际读取并验证 OSS,短事务内锁执行引用表、版本及定位,重查 cutoff、非当前版本、执行引用与摘要一致后置空快照。版本行和执行引用外键不删除,冷历史仍从 OSS 读取;已有执行引用的热快照不释放。定位在冷状态下禁止 UPDATE/DELETE。恢复服务从校验后的 OSS 内容回填,数据库再次校验原 JSONB 摘要,随后移除定位,保留 OSS 对象。

回滚必须先用新代码恢复全部冷版本,再运行 cold_snapshots rollback,最后回旧 Web;若还需移除定位表,在前述恢复/迁移后运行 locations rollback。两个 rollback 均先持有版本表 ACCESS EXCLUSIVE 锁再检查空快照,存在冷版本即拒绝;避免检查后并发释放导致定位丢失。此功能仍未开放自动维护入口,引用覆盖范围与运行负载仍需完成发布前验收。

Skill 内容依赖索引(开发候选)

20260905_user_skill_dependencies.sql 新增 user_skill_content_refs(source_kind, source_key, skill_id, revision),主键为四字段,目标版本另有索引。source_key 是源表主键字段的 JSON 数组文本,避免拼接碰撞;不存原文。覆盖画布 document、操作/逆操作、Agent messages、当前 Skill manifest/source_ref、历史 snapshot。UUID 大小写归一,版本只接受正安全整数,非结构自由文本不算引用。

五张源表的语句前触发器先取得依赖表 ROW EXCLUSIVE 锁,行后触发器在同一事务更新依赖;源主键修改清旧引用,源删除清理对应引用。历史快照转冷不清其依赖,回填后按原内容重建。首次迁移锁住源表后回填,若已有冷快照则拒绝并要求先恢复;已完成迁移的重跑不清除冷历史依赖。

归档登记/释放同时检查执行引用和内容依赖;短事务内依赖表 SHARE ROW EXCLUSIVE 锁将维护任务串行化,并与源写入互斥。源保存/维护双向并发与提交后重查已通过实际 PG 触发器验证;业务延迟仍待验证,维护入口仍未开放。依赖迁移回滚要求停用维护任务并恢复所有冷快照,随后移除触发器和索引表;不会修改源文档。

归档策略复用 app_state 的 skill-archive-policy 键,data 保存 retentionDays、revision、updatedBy、updatedAt。不存在时读取默认未配置状态;写入通过期望 revision 条件 UPSERT 防覆盖,记录当前管理员身份,读取无归档副作用。未新增表或修改现有 schema;CLI 的显式 cutoff 不由此配置隐式覆盖。

步骤尝试的 Skill 执行引用绑定(开发候选)

20260905_agent_plan_step_attempts_refs.sql 在尝试插入事务中核对快照所属用户仍有画布 owner/editor 权限(成员行 SHARE 锁)、步骤 ID 唯一且 Skill ID/revision 匹配、Skill 归属一致,然后以 operation_id 登记 user_skill_execution_refs。相同引用仅允许相同版本与画布;失败回滚整次插入。快照 UUID 文本大小写等价,不接受畸形文本。

此触发器是存储完整性保护,不是完整 DAG、素材权限、报价审批或执行准入。尚未开放尝试写入 API;既有尝试回填及完整归档并发联验仍待部署前完成。回滚持有尝试表排他锁,非空时拒绝移除保护;空表回滚保留既有执行引用。

Skill manifest 的开发候选新增可选 outputs 数组,保存命名输出与 image/video/audio/text 类型;仍存现有 JSONB 并随正常 Skill revision 保存历史,不回填旧版本。缺失不等于空契约,也不表示已验证媒体输出。旧版本 Web 的 manifest 规范化会丢弃此新增字段,因此回滚旧 Web 后应暂停编辑含输出声明的 Skill,避免创建丢失契约的新修订;历史修订仍保留。

Skill manifest 的 inputs 亦支持可选 kind(image/video/audio/text),同样沿现有 JSONB 与历史修订保存。缺失保持未知,不迁移回填。旧 Web 编辑可能丢弃 kind,回滚时应暂停编辑带类型契约的 Skill;不改变旧历史修订。

解析输入快照(开发候选)

agent_plan_resolved_inputs 以 (snapshot_id, step_id, input_sha256) 为主键,引用计划快照,保存精确 serialized_inputs TEXT(最多2MiB)与创建时间。数据库复算 UTF-8 SHA256 并核对序列化内容内的快照ID、步骤、协议版本与 inputs 数组;UPDATE 被拒绝。完整输入 schema、真实素材校验和步骤归属仍由后续准入服务负责,当前没有写入 API。

迁移 20260905_agent_plan_resolved_inputs.sql 已加入平台入口;down 先取得表排他锁,有数据时拒绝,空表才删除。父计划快照删除会级联清理;目前尚未与执行尝试建立引用约束,不能当作已持久化执行锁。此表含用户文本,读取必须沿所属计划鉴权,不输出正文到诊断日志。

20260905_agent_plan_resolved_inputs_refs.sql 将尝试的 (snapshot_id,step_id,input_sha256) 外键关联到解析输入表;新增尝试缺少精确输入记录被拒绝,被引用输入禁止单独删除。迁移校验既有行,缺失历史输入时失败,不生成替代内容。回滚顺序为先停用尝试写入、处理现有尝试后移除引用保护,再执行输入表回滚;引用保护 down 持尝试表排他锁且要求空表。仍需准入服务在同一事务核对授权、保存实际输入并登记尝试,单有外键不是执行许可。

agent_plan_requests(不可变生成请求,开发候选)

20260905_agent_plan_requests.sql 注册在解析输入迁移之后。主键为 (snapshot_id,step_id,request_sha256),通过 (snapshot_id,step_id,input_sha256) 外键绑定精确解析输入。serialized_request 最多2MiB,数据库验证 UTF-8 SHA256、快照ID、步骤、输入摘要、协议版本及字段数组;拒绝 UPDATE。输入删除级联清理请求;未来审批与尝试接线时还需建立对应引用保护,当前不构成执行锁。

内部 savePreparedPlanRequest 在 REPEATABLE READ 事务中核验当前 owner/editor、锁定成员记录,从服务端按作用域读取解析输入后编译并幂等插入;不接受调用者传入解析正文。同参数保留同一请求,参数变化产生新摘要,不修改旧记录。返回摘要与模型,不返回提示词正文。尚无对外写入API、报价审批或任务下发;down 在排他锁下拒绝非空表,仅空表允许移除。

agent_plan_step_events(执行事件基础,开发候选)

迁移 20260905_agent_plan_step_events.sql 在步骤尝试和输入引用之后执行。event_id 唯一;operation_id 外键关联尝试;kind 限定队列、提交、运行、成功、失败、中断及待核对状态;detail 为最多16KiB的JSON对象,写入方须限制为业务诊断,禁止秘密/原始请求正文。sequence 为BIGINT identity,用于查询排序,但分配顺序不是提交顺序,不得未经并发协议直接当作无遗漏SSE恢复游标。

UPDATE触发器拒绝修改历史事件;删除父尝试级联清理事件。down迁移锁表并拒绝丢弃非空事件。尚无公开写入接口;事件合法性与状态转换、外部任务核验、幂等事件重放由后续执行器实现,单独插入事件不是执行授权或生成成功证明。

内部 appendPlanStepEvent 使用尝试行锁串行写入,同一event_id与同内容重试返回原sequence,内容冲突拒绝。首次只能queued,后续按状态转换表推进;succeeded/failed不可重新打开,interrupted必须先进入reconciliation_required。待核对→running只表示外部原任务经核对仍在运行,不表示允许重新提交。调用方仍须提供可信外部证据,当前无公开事件写入口/执行器接线。detail仅接受code、externalTaskId和0–100整数progress,不接受任意正文。

审批快照及请求引用(候选)

agent_plan_approval_snapshots 保存规范化审批材料,不等同已批准执行:sha256 为主键,snapshot_id 外键限制删除计划快照,serialized 最大1MiB并校验UTF-8 SHA、schemaVersion和snapshotId;UPDATE触发器拒绝修改。

INSERT触发器从材料内1~1000项requests自动写入 agent_plan_approval_request_refs,主键为 (approval_sha256, step_id);每项通过 (snapshot_id, step_id, request_sha256) 引用持久生成请求并限制其删除,任一请求不存在时整个INSERT回滚。删除审批材料会级联清理引用;此操作必须由后续保留策略/审批生命周期服务控制,当前无对外删除入口。

迁移 20260905_agent_plan_approval_snapshots.sql 在生成请求表后执行;对应 .down.sql 在独占锁内拒绝非空审批表,空表才允许回滚。当前仅完成表结构与最小父表PG验证,尚无鉴权审批写服务、完整迁移链验收或生产部署。

审批决定(候选)

agent_plan_approval_decisions 每个 material_sha256 仅保存一次 approved 或 rejected,通过限制删除外键保留材料及审批人;created_at 默认数据库时间,UPDATE拒绝。INSERT触发器绑定材料内approvedBy与actor_user_id,批准时要求数据库时钟处于材料有效区间,缺失时间也拒绝。记录存在不等同已完成预算预留、入队或实际执行,业务服务仍须验证当前画布权限和请求。

20260905_agent_plan_approval_decisions.sql 在审批材料迁移后执行;对应down迁移独占锁后拒绝非空表。此阶段仅完成表级校验及最小父表PG测试,尚未接入审批API或生产。

agent_plan_dispatch_outbox

持久待下发意图,以operation_id为主键并引用准入关联,删除RESTRICT;默认pending_validation,另有ready/leased/submitted/reconciliation_required/failed。租约token、owner、expires仅在leased状态存在,领取次数非负且leased时大于0;operation与created_at不可修改。ready可用时间及leased过期时间有部分索引。迁移20260905_agent_plan_dispatch_outbox.sql接在admissions之后,down拒绝非空表。内部准入服务已在预留/attempt/准入关联同事务内创建待验证意图,重放要求整组关联完整,不自动补造缺失意图;尚无领取器或验证通过状态转换。数据库行不是媒体验证、执行授权或供应商成功凭证。

agent_plan_admissions

不可变准入关联:operation_id UUID主键引用步骤attempt,approval_sha256引用审批决定,reservation_id唯一引用既有积分预留;父记录删除均RESTRICT。插入触发器核对同一快照/步骤的审批请求与attempt输入摘要,批准者、计费账户、供应能力、模型、单位、数量、单价、金额及初始held状态。该表不承担调度,也不替代应用事务的权限、有效期、预算和媒体检查;预留后续正常结算不修改此历史绑定。增量迁移 20260905_agent_plan_admissions.sql 在审批决定迁移之后;down对非空表拒绝,须先完成显式对账保留评估。

Agent 计费 ACK 持久队列(候选)

20260906_agent_billing_ack_outbox.sql 新增独立队列,按 operation_id 关联 admission,保存 namespace/task ID、重试次数、下次执行时间、确认时间和受限错误码;任务身份不可更新、确认时间不可撤销、计数不可递减。外部任务唯一,未确认队列有局部索引。

计划由成功结算事务原子入队,事务提交后单独发送 ACK,失败保留重试,不重新生成或改账;图片完成器已在成功结算事务内原子入队,独立发送已接入 Worker CLI:同一待办最多每60秒尝试一次,仅 HTTP 成功且 ok=true 后标记确认;5秒超时、协议错误和404均保留重试。历史补录每轮最多20条,须同时匹配已结算账本、成功事件的外部任务ID与同画布结果操作;只补缺失的ACK记录,不重放生成或结算。回滚持排他锁,非空表拒绝删除,保留已有证据;此迁移不改现有积分与生成记录。

直播间复杂动作触发

live_room_keyframe_transitions.trigger_event 支持独立的 complex_action 值,用于多段复杂动作最终素材的模拟、审核与发布前状态图校验。既有 auto、idle、typing、gift、action、preview 保持兼容。

DSH 直播角色生产运行

迁移 20260908_dsh_runs.sql 固化此前运行时初始化的 dsh_runs 表:每条记录绑定画布项目和发起用户,保存不可替代生成证据的计划、当前派发位置及步骤记录。步骤记录中的 dispatched 只表示画布节点已经创建;succeeded 需要服务端核对 generation operation、供应商终态、积分结算、生成来源和已登记媒体,仍表示“等待人工质量验收”,不会把文件存在等同于角色生产完成。任务中心按当前画布成员权限读取并投影这些记录。

迁移 20260908_harness_skill_lockfile.sql 为 DSH Run 增加统一 Harness 引擎标识及 Run 级 skill_lockfile。锁文件由服务端依据持久计划一次生成,固定协议版本、Skill 标识、版本、来源和内容 SHA-256;数据库触发器禁止运行开始后替换锁文件或摘要。旧 Run 读取时只投影确定性的内置锁文件,不反写或伪造历史用户 Skill 引用。Codex 运行继续使用既有不可变 user_skill_execution_refs,后续由统一 Harness 查询协议聚合两类来源。

迁移 20260908_generation_quality_reviews.sql 新增生成记录人工质量评价。每个 operation_id 仅保留一份当前评价,包含 Good Case/Bad Case、Bad Case 必填原因、备注、调优状态和管理员审计身份;生成记录删除时评价随之清理,管理员删除受限时不会留下无归属审计行。筛选索引覆盖评价、调优状态和更新时间。

迁移 20260908_generation_quality_reruns.sql 为评价记录增加 rerun_operation_id 与复跑时间。复跑必须创建新的计费 operation,并由执行复跑的管理员账户预扣和结算积分;评价记录只保存关联,不复制或篡改原任务账本。新旧结果保持独立,可在管理员生成记录中对照预览。

回滚脚本只允许删除空表;已有运行历史时直接拒绝,避免为了回退代码删除任务、节点和产物的关联证据。

直播间多人房参与者

迁移 20260907_live_room_participants.sql 新增 live_room_participants:每个直播间保存参与者声明,participant_id(4-64 位 [A-Za-z0-9_-])即编排模型里的参与者 id,房间内唯一;kind 限 ai/human,(live_room_id, participant_id) 唯一,ON DELETE CASCADE 随直播间删除。首期上限(真人与 AI 合计 4 名、AI 最多 2 个)不在表约束而在插入事务内以 FOR UPDATE 行锁重读参与者后由共享 validateParticipants 裁决,防止并发超限。

关键帧多人联合锚点声明

迁移 20260907_live_keyframe_multi_anchor.sql 为 live_room_keyframes 增加 multi_anchor JSONB(可空):participant_slots、character_order、occlusions([前, 后] 对)与 sync_anchor,仅 multi_anchor 层级要求非空且全部引用房间已声明参与者,写入前由 validateMultiAnchor 对照 live_room_participants 裁决。

直播间仅链接分享

迁移 20260907_live_room_share.sql 为 live_rooms 增加 share_token TEXT UNIQUE 与 shared_at TIMESTAMPTZ。启用即生成 base64url token(幂等复用),取消置空后链接立即 404;公开只读接口 /api/live-room-share/[token] 不要求登录,仅返回角色卡/关键帧元数据/状态图,不含媒体 URL 与画布数据。

  • 状态素材转场允许 idle、typing、gift、action、complex_action、preview 同锚点自循环;auto 仍要求不同关键帧。迁移 20260908_live_room_state_loops.sql;回退保留已存循环数据并限制新写入。

直播间素材分区

20260908_live_room_asset_screen.sql 为 live_room_keyframes 增加 screen(public/private)与 (live_room_id, screen) 索引;旧数据按原直播间 screen 回填,不复制或删除媒体。新建后分区不可修改。

转场通过首尾关键帧推导分区;数据库触发器要求首、尾及回退帧属于同一房间和分区。已发布快照保留每个关键帧的 screen,旧快照回滚按原房间 screen 解释。

Canvas 关键帧 GET 支持 ?screen=public|private|all,仍要求项目成员鉴权;省略时沿用房间 screen,Partner 既有接口不自动混入另一分区。

降级脚本 20260908_live_room_asset_screen.down.sql 仅在不存在私人关键帧时允许删除新增字段;已有私人素材时失败保护,禁止直接回退到不识别分区的旧 Web 镜像,应以前向修复保留私人资产。

用户头像

users.avatar_storage_key 为可空的 media_objects.storage_key 外键(删除媒体时 SET NULL)。上传头像仅可绑定当前活跃账号拥有、2 MB 内的 JPEG/PNG/WebP 媒体。头像删除只清空引用,保留媒体;回滚先切回旧 Web 镜像,再执行 web/migrations/rollback/20260910_user_avatar.sql。

Canvas Lab 独立测试平台数据库

apitest-platform/ 使用独立 Compose PostgreSQL 实例的 infinite_canvas 数据库,不复用画布或其他项目数据库凭据与数据卷。

表数据
apitest_assetsUUID、图片/视频类型、文件名、OSS key、MIME、字节数、宽高、预留位与创建时间;(kind, slot) 唯一
apitest_runs请求路径/方法/格式、脱敏参数、素材 UUID 数组、HTTP 状态、耗时及脱敏响应
apitest_settings接口预设 JSON;不保存 API Key

权威幂等加法初始化见 apitest-platform/src/lib/server/db.ts,首次种入 100 图片与 100 视频空位。文件上传先填空位后追加;媒体本体仅进入 OSS ic-apitest-platform/ 前缀。初次发布回滚仅停止平台 app,保留全部表、数据卷和媒体;回滚脚本见 apitest-platform/scripts/rollback.sh。

On this page