文档
07 过程记录04 会议与复盘

PROC-04-003 Creative与Studio及Commerce架构审计(2026-10-28)

2026-10-28跨项目架构复盘的只读审计附件,事实与建议分列,不构成批准决策。

本页是跨项目架构深度复盘的过程附件。观察事实、静态推断和建议分别阅读;建议不构成已批准决策,不修改既有ADR/PRD。版本、线上取证与未验证范围统一见审计证据。

源码链接固定到审计记录的完整提交;未提交工作副本、无法固定的本地材料明确标注,不以相近提交替代。固定链接只证明所引源码,不证明部署、性能或真实付费验收。

审计时间:2026-10-28。方式:只读源码、规则、交接文档、Git 状态及提交差异;未启动服务、操作业务库、调用付费模型或修改产品代码。本报告的代码行号对应本次实际 checkout。用户确认新的 Studio 重制项目是 oceanway-creative。EXA 指 Platform 的执行授权,不是外部 Exa 搜索服务。

1. 最重要的结论:目前同时存在三套不同阶段的 Studio 架构

对象本次观察能证明的现状
oceanway-creative710e20c61c8243f6d1aaf24c7e5aff9428286ac1,分支 codex/oceanway-bootstrap,工作区干净;git diff cd694236f82e2851393cadc0150ebbde375cdc81 -- backend web 无输出Go + React + Pi 底座已经 fork;业务源码仍与固定上游完全一致,Oceanway Platform/Media 尚未接入
oceanway-studio main90eba1abe43fc2ee76eb5cfb4f6f43f04af90f80,有既存未提交 run-client.ts 及相邻测试修改Next.js 旧 Studio 中已经出现直接 Platform 生成、非流式文本原响应恢复;不能等同运行版本
Studio 历史工作树oceanway-studio,38028fe50f9c64883c99ada416757d587f892055,干净历史实现对照,仍保留 Runtime 生成主链,没有 main 的 direct-text.ts 和 execution-text-client.ts;不是本次确认的线上制品
Studio 线上容器主任务本轮只读 Docker inspect:容器名含 38028fe,但 image revision label 为 90eba1abe43fc2ee76eb5cfb4f6f43f04af90f80;编译 chunk 包含 oceanway.text-request.v1部署端已经包含新的文本消费代码;不能根据旧容器名或历史恢复记录断言仍在运行 38028fe。实际付费恢复流程尚未验收
oceanway-commercea0590570ec15ac77e895e01a536ec392a3527fbf,main,干净React + FastAPI,已经通过 Platform EXA/native/materials 接中央服务;文本恢复仍落后于旧 Studio main

Creative 的交接文档本来就坦诚标注未完成,不应把未完成底座当成已经发生生产事故:

  • HANDOFF.md:20:业务源码仍为固定上游,Platform/Media adapter、产品身份、交互迁移和新部署均未实现。
  • HANDOFF.md:24:P0/P1 未完全关闭,P2 未开始。
  • implementation-plan.md:7:原计划是 Studio/Drama/Commerce 在同一 Go 工程内共用工具机制,先不拆微服务;它是计划,并非当前运行事实。

架构管理的首要偏差不是“完全没有中央能力”,而是中央能力、各产品消费实现、main、运行制品及重制计划没有一个共同的能力版本矩阵。主线出现代码后,文档很容易把它写成所有产品、所有部署均已具备。

2. Creative 当前真实调用链

浏览器 React/Vite
  -> /api/auth/* 自建登录 / open_ai_canvas_session
  -> /api/tasks / 画布 / 项目 / 资源 API
  -> Go handler -> service 别名 -> app 组合根 / 域包
  -> 自有 PostgreSQL/SQLite User、Session、Task、Resource、BillingOrder
  -> 本仓 Worker -> providerConfig / SystemChannel -> 供应商协议
  -> 供应商结果下载 -> 本机暂存 -> 本机 resources 或自配 OSS/S3

自由 Agent 另经 Pi/yingce-agent 调同一 Task/工具系统。
当前这条链没有 Oceanway Platform identity / EXA / materials adapter。

2.1 登录和权限仍是上游自己的账号系统

含义:如果只改登录页面样式、把 Platform 账号同步成一个本地用户,而继续用本地 Role/Session 作权威,就会出现两套账号封禁、退出和运营权限。正确接入是以 Platform subject/session/product roles 为当前可信 principal,业务 User 仅作为映射与产品资料;不另签出能绕过中央撤销的长期本地身份。

2.2 internal/platform 不是 Oceanway Platform

platform_bridge.go:8 import 的是 yingce/backend/internal/platform;同文件:68 创建的是本仓 runtime policy、并发、功能开关、审计服务。文件名很容易被后续开发误判为“Platform 已接通”。新 adapter 应用明确命名(例如 internal/oceanway/platform),避免把上游局部概念当中央服务。

2.3 模型执行与费用仍由上游本仓拥有

这不是可以仅“换 BaseURL 指向 Platform”完成的改造。中央接入必须替换供应派发/供应轮询/钱包分支,否则产品和 Platform 同时成为执行及账务权威。Go Task 的业务生命周期、队列领取、租约、画布回写可保留,供应商取消/退款事实只能消费中央结果。

2.4 原件当前仍写自己的磁盘或自配存储

计划要求相反:AGENTS.md:8 与 implementation-plan.md:72 要求 Platform materials → Media → oceanway-media-assets-cn,不新接旧 File Owner、不独立原件权威。新 Resource 应承载中央引用和产品关联,不再由各产品配置同一个桶密钥“看起来共桶”。本机临时 FFmpeg 输入输出与浏览器未同步 Blob 可存在,但不成为已保存原件的权威。

2.5 自带 /admin 会与统一运营后台重叠

router.tsx:221 的上游 /admin 包含用户、渠道、模型、支付、存储、积分、兑换码、登录策略、邮箱、更新器,也有提示词/公告/反馈。这些不能整套改名叫“Studio 运营后台”后继续保留。

建议界限:中央账号、准入、模型发布、资金、共享素材及其管理由中央服务掌握;统一运营后台提供入口及授权动作编排;Creative 只保留其产品内容和领域命令。运营后台不能直接改 Creative 数据表绕过版本、成员、采用规则。旧 Studio 内容权限已经有可借鉴边界:work-admin-authority.ts:15 要求当前 Platform studio:admin,且重新核对主体和会话。

3. 已中央接入产品的真实差异

3.1 容器名、历史工作树和运行制品必须区分

旧 Studio main 的直接生成:direct-platform.ts:77 明确 executionOwner=platform 且没有 runtimeRunId;direct-text.ts:59 明确单次产品文本调用不创建 Runtime Run,先保存请求身份,恢复只读原响应。

历史工作树 38028fe 的 service.ts:82 在 directCanvasMedia 场景仍返回 ensureRuntimeCoreRun;compose.ts:63 真正调用 Runtime submitRun;service.ts:116 owner 只有 embedded/service。此历史版本没有 main 的 direct-text / execution-text-client 文件。

主任务随后直接只读线上 Docker image label 与编译制品,确认容器虽然名字带 38028fe,实际 image revision 是 90eba1a,且 web/.next/server/chunks/_07pitpk8t8vkp._.js(容器内编译制品) 含 oceanway.text-request.v1。Platform 的 image label 虽指向不含该合同的 ecac00e,实际二进制却包含合同和路由字符串;无凭据 GET 文本恢复路由返回 401 PLATFORM_PRODUCT_REQUIRED,不存在的对照路由返回 SPA HTML。因此线上合同入口已存在,不能断言 Studio–Platform 缺少配套恢复端点。问题是制品来源元数据与实际二进制不一致;授权后的端到端恢复本轮仍未验收。具体证据由主报告和 线上只读取证 保存。

3.2 Commerce 已走中央服务,不应再归类为旧本机供应网关

3.3 已发生的契约分叉:Commerce 文本仍没有原响应恢复

证据非常明确:

  • text_jobs.py:26 创建业务任务、申请 EXA、claim,然后 同文件:44 普通 client.json(POST,/internal/relay,body);没有 X-Platform-Text-Request-ID、恢复协议预检或原生字节冻结。
  • text_jobs.py:57 将 HTTP/解析/验证失败统一标为 unknown+failed;image_jobs.py:198 重启恢复文本只是等待 31 分钟后标失败,没有 GET 原请求。
  • 拍摄清单规划另有独立实现:image_jobs.py:47,同样发普通文本 POST 并用时间阈值落 unknown。
  • 对照旧 Studio main:execution-text-client.ts:44 发送前 GET 验合同;同文件:50 固定原 call ID 发一次;direct-text.ts:134 无响应时仅 GET 原请求。

实际后果是已收费成功文本在断线、重启、解析前失败后无法由 Commerce 产品恢复,用户只看到失败。现有 claim 仍阻止同 command 自动重发,因此不能据此宣称已重复扣费。这个例子证明公共问题已有不同实现,最值得优先合并的是可恢复请求协议及其一致性测试,而非统一按钮组件。

3.4 授权分叉:Commerce 后台素材仅支持 EXA

  • Commerce native.py:65 grant 只接受 exa_;同文件:35 上传也只接受 EXA;没有 mat1 消费。
  • Studio main material-client.ts:11 保存独立材料授权;同文件:39 binding/释放优先用仍有效 mat1,避免 EXA 停止后无法完成素材收尾。
  • Commerce image_jobs.py:126 保存/确认仍使用 EXA;PlatformError 时保留运行等待 同文件:139。EXA 过期或撤销后如仍需素材写操作,缺合法新材料授权路径,可能长期等待。已有输出下载用当前用户 Cookie 同文件:313,这部分处理正确。

此项是代码路径推断出的恢复缺口,未做真实过期/撤销联调,不能写成已复现线上故障。

3.5 文件传输实现重复且效率不同

Commerce materials.py:18 用 chunks + join 全量缓冲;同文件:67 512 MiB 上传全部进入内存后再转发。大量视频并发上传会放大内存峰值。旧 Studio 的统一素材说明已要求流式转发 unified-account-assets.md:7。共享资产 transport 应统一流式限制、hash/length 校验、取消语义和凭据隔离,而不是让每个产品另写上传代理。

4. 应当抽出的公共模块

目标是共享契约和薄客户端,保留产品自己的业务任务、事务和领域模型。不要从旧 Studio 整体搬出 studio_runtime_* 或再创建通用 Runtime 服务。Creative 已明确禁止旧 Runtime,并选定 Go Task/Pi;跨语言共享重点应是规范、fixtures、版本及客户端实现。

公共能力所有权 / 推荐形态必须包含不应包含
Platform contract bundlePlatform 维护版本化契约及兼容测试,供 Go/TS/Python 消费identity/principal、目录、EXA、native relay、text recovery、errors、ID/金额格式、发布能力版本产品 UI、产品 DB
Platform clientGo、TS、Python 薄客户端,Transport 注入session 与 worker 两种独立 request builder、凭据禁止混传、超时/响应大小、EXA 签发/释放、原结果查询自动重试收费 POST、供应商路由、第二套计费
Account assets clientMedia 合同,经 Platform materials 访问mat1/EXA 边界、upload intent、exact asset/version/file、bindings confirm/release、容量视图、短期下载、流式 I/O产品自行持桶密钥、复制中央原件、以签名 URL 作持久 ID
Catalog/native parameter helpersPlatform 发布 schema,由客户端做确定性校验与序列化frozen revision、native endpoint、reference roles、defaults、specification validation每个产品私有模型预设、暗中降级供应商
执行结果投影与请求身份规范共同合同;持久化仍由产品拥有command/call/attempt、原生字节指纹、EXA、task ID、operation ID、asset lineage、UNKNOWN/保存中含义通用产品业务状态机或统一全部业务表
产品运营授权 SDK中央 current session + resource/action 权限,产品服务再核对象actor、product、action、target、版本条件、审计关联、统一错误“后台是内网所以免鉴权”、直接跨库 CRUD

共享 request builder 的接口应区分三类:

  1. SessionRequest:用户当前会话 + 注册产品 key + 真实 Origin;用于身份、目录、EXA 签发、材料授权。
  2. ExecutionRequest:原产品 key + 原 EXA,无 Cookie/Origin;用于已获授权任务的首次调用及原结果读取。
  3. MaterialRequest:原产品 key + mat1 或 EXA 二选一 + 预期账号;用于原件、引用、归档完成。

exa_ 是执行能力,不能被理解成登录 token,也不能被理解成所有 POST 的幂等凭证。EXA 幂等签发只保证同业务引用得到同授权,不保证媒体首次回包丢失后还能定位原供应请求。见 platform-media-contracts.md:78。

5. 重制下一步的具体顺序

  1. 先建一张每产品、每部署的能力矩阵,至少列:identity、目录版本、EXA、直接文本恢复、媒体 receipt、materials/mat1、公开结果投影。每行记录源码 SHA、制品 digest、验收证据、未闭合事项。把 Studio main、实际 image revision、历史 38028fe 工作树明确分开,特别核验 Studio 与 Platform 的配套能力。
  2. 将 Platform/Media 已有真实协议抽成可发布 contract bundle 和共享 fixtures。用旧 Studio main 与 Commerce 作为两个消费者跑一致性测试,先揭露分叉,再抽客户端;不从三套现有实现各复制一份到 Creative。
  3. Creative P2 第一纵向闭环:中央登录/准入 -> 发布目录 -> 一个直接非流式文本 Task -> 原请求恢复 -> 业务回填;停止新入口本地密码/钱包/供应凭据路径。随后接一个图片 Task -> 原 artifact -> 中央素材绑定。
  4. 更换 Resource 引用和所有上传/导出入口;统一素材是账号共享,任务/会话/项目仍按产品、surface、成员和创作者权限独立。Creative 当前 Task 主要只有 UserID/ProjectID,需要明确新增产品作用域或证明部署单产品隔离,不应只靠 UI 路由名称。
  5. 将统一运营后台接到产品领域命令,先覆盖提示词/公告/审核等边界清楚的内容运营;中央账号/付费/模型/存储动作走中央管理能力。停止上游 /admin 中重复的权威配置及其后台进程,不能只隐藏菜单。
  6. 再做 Agent/Pi、并发、交互迁入。上游 Worker/Canvas CAS 可以保留;模型回调和工具结果必须受原任务 owner/epoch、业务对象版本约束。旧 Runtime 任务只按原归属读/排空,不能导入新 Creative 重跑。

建议合同验收至少覆盖:同 command 改正文拒绝、EXA 撤销/到期后读取与写入的差别、mat1 撤销、提交后进程中断、结果取得后保存失败、媒体首回包丢失、跨账号与跨产品对象访问、旧结果晚到不覆盖新编辑、上传并发内存边界。这里没有执行这些验收,不能将此清单视作已通过。

6. 审计边界

  • 未评估新的 Drama 重制实现,交由主任务其他审计分支。
  • 新统一运营后台的实际仓库、PLAT-02-037/038/039 与容量政策版本由主任务统合;本报告仅评估 Creative 自带 admin 和旧 Studio 内容后台边界。
  • 线上 Studio 制品 label 和编译 chunk 证据由主任务直接只读获取;本分支直接核对 main 与历史工作树代码。历史恢复记录/容器名称的 38028fe 已被本轮实际 image label 90eba1a 纠正,报告不再将前者写为运行基线。
  • 未运行测试、构建或浏览器;结论是源码与合同审计,不是性能、线上 IAM/TLS、付费成功或桶运行配置的验收。

On this page