PLAT-04-014 Platform重构项目接入实施计划
优先交付固定接入合同、媒体原请求恢复、产品资源接入及独立Go客户端,解除重构产品对Platform的依赖阻塞
For agentic workers: Use superpowers:subagent-driven-development to implement task by task. Each task requires focused verification and independent review.
Goal: 先让重构项目有固定、可验证的Platform接入方式,再推进运营工作台;交付代码、正式契约、Go客户端及隔离验证,不能只交接口清单。
Architecture: 复用Platform/new-api现有会话、EXA、原生Task、计价及Media代理。提供方维护一个独立Go客户端模块,消费方不引入new-api服务根模块、不复制计价或恢复状态机。已有个人路径先形成完整可用合同;团队付款、团队素材及员工跨产品委托必须明确能力边界,不能静默替换为个人或全局权限。
Tech Stack: React、Go、PostgreSQL、Redis;本计划不开发运营UI或新的Node/Python服务。
Spec: 跨项目公共能力收敛实施计划。用户已授权开始执行,并明确Platform接入优先于运营界面。本页记录提供方实施细节,不扩大为全部产品重制或整套商业新增功能。
Global Constraints
- 保留多仓、Platform的new-api底座和根Go module路径;不重建身份、钱包、供应引擎或旧Run执行层。
- 业务产品身份为studio、drama、commerce;Creative是跨产品画布与Agent基座,承接哪个产品就保持该产品的凭据、授权和对象范围,不能整体归为studio。仓库、承载实现与业务产品ID分开;共享宿主验收见DEV-X-01-008。
- 模型目录包含全部适用模型;仅图片/视频展示生成费用预估,文本正常调用与计费。
- 产品密钥、用户会话、EXA、mat1严格区分;后台执行不携带Cookie、Origin或用户Authorization。
- 未知付费提交不自动重发、不自动退款;只恢复原请求。模型结果、结算和产品保存分别保留事实。
- Media拥有原件、容量使用及引用;产品对象权限留在产品。无旧Node/Python兼容要求,不删除历史数据。
- 业务代码使用隔离worktree。只运行自有隔离数据库/受控上游夹具,不访问生产秘密、不真实付费或部署。
- 源码仓仅保存机械契约、运行说明及具名验证材料;计划与进度分别在docs正文和07过程记录。
Review Focus
- 首次媒体响应完全丢失、并发重复、重启后恢复:必须返回同一原生Task且无第二次供应调用/扣费,由Task 1测试。
- 同请求ID但正文、协议或路径不同:拒绝冲突;跨产品/授权/用户不能读取,由Task 1测试。
- Drama项目同步伪造归属、账户、成员及版本:Platform与Media边界均不因开放产品而扩大,由Task 2测试。
- 客户端重定向、错误内容或凭据混用:不泄露服务密钥、不自动跟随带凭据请求到外部,不把HTTP 200失败当成功,由Task 3测试。
- SSO的Host与Cookie、原生响应/JSON信封/二进制、原始请求字节:分别保持原合同,未知不重派,由Task 3测试。
实施边界与复用
当前身份、产品目录、个人媒体消费预览、EXA及材料代理已有实现。Creative尚无中央接入客户端;Drama有内部客户端但费用预估、统一素材未接,这些不等于提供方从零缺失。旧product-media original locate只查询历史PlatformOperation,不能定位现行EXA原生Task;本计划在原生Task链补调用方稳定请求身份,不恢复旧创建链。
团队消费预览和EXA目前以个人主体为边界;本计划的客户端必须拒绝或不暴露未支持的团队付款参数。团队资金及容量完整接入沿团队工作包完成,验收记录不得写成全主体已具备。生产制品尚须经后续发布核对,本地代码/隔离通过与已发布分别交接。
Task 1: EXA媒体稳定请求身份与原任务恢复
Files: 修改model/task.go、service/task_submission.go、controller/platform_session_media.go、router/platform-session-relay.go;新增service/platform_execution_media.go、controller/platform_execution_media.go及相应测试;更新docs/openapi/platform.json及新的platform-execution-media.fragment.json、router契约测试。若现有Task更新路径需要保持原绑定,只修改直接相关字段保存点。隔离测试入口scripts/platform-commercial-test.py补齐本任务所需native-responses独立数据库与DSN映射,不继承环境凭据;缺少DSN导致的skip不计为RED或GREEN。
Interfaces: 使用X-Platform-Media-Request-ID,值匹配^[A-Za-z0-9_-]{1,128}$;新增GET /internal/relay/media-requests/:request_id。提供BindPlatformExecutionMedia/ReadPlatformExecutionMedia,沿现有EXA和Task体系。GET返回版本oceanway.media-request.v1、request_id、task_id、status和原任务可用性;不创建或重派任务。身份绑定EXA、用户、产品及请求ID,指纹涵盖方法/协议/原生路径/有效查询和原始正文,不能借同ID改成另一生成。
- 在真实隔离PG先添加失败测试:带稳定ID的图片/视频提交,丢弃首响应后GET能取得原Task;并发相同提交只派发一次;异正文409;异授权不能读取;失效/释放按现行EXA原读取政策恢复。
- 原始绑定在任何计费和派发之前持久化,复用原生Task及PG并发锁;不另建资金表或通用任务服务。BeginTaskSubmission及最终更新保留绑定,原生确定拒绝重试仍使用同一Task。
- 重复POST只能读原结果或返回原任务处理中,不重新准入收费。第一次绑定后进程失联保持可查未知;未找到也不自动授权客户端重派。新增头不传到供应商。
- 仅现行EXA媒体入口承诺此合同;未带头的既有Go原生请求沿原行为。SDK后续对媒体提交要求调用方稳定ID。覆盖图片、视频及具备媒体profile的Gemini,拒绝把此能力用于文本或流式请求;multipart保持原字节和边界。
- 更新完整OpenAPI引用闭包并运行路由契约验证;真实PG测试覆盖供应次数/原Task/资金结果,意外skip不能算通过。已有文本恢复及原生Task相关回归按影响运行。
- 记录测试和源码;提交本任务修改,供独立评审,不推送/发布。
Task 2: Drama项目资源同步正式接入
Files: Platform的controller/platform_assets.go、controller/platform_assets_test.go,相关service素材授权测试及docs/openapi/platform-account-assets.fragment.json/platform.json、docs/unified-account-assets.md。Media的service/unified_asset_projects.go、service/unified_assets.go、相应项目/查询测试及docs/unified-account-assets.md;必要HTTP合同测试只覆盖本任务路径。Media基线固定7bf5cc18e119d16fbc4837af13b45d7c4e507836,独立分支codex/media-integration-readiness,不改其他任务checkout或旧网关仓库。
Interfaces: 复用PUT /internal/materials/projects/:project_id、现有账户绑定、产品凭据和EXA/mat1。正文为title/path/revision/deleted/members,成员为Media的asset_id/version_id,不接受owner/app字段;身份来自签名。Drama路径精确为现行前端helper生成的/creative/drama/steps/1?projectId=<project_id>(按URLSearchParams语义编码;当前项目ID为小写UUID),不采用假设的/projects/{id}或旧入口。完整路径须与原项目ID一致,拒绝额外query、其他step、外部URL。Drama与Studio/Commerce具有相同的受限项目写入能力,不能伪造app或其他账户。
Snapshot semantics: revision为产品资源快照单调序列;较低revision成功但不更新,同revision同正文幂等、异正文409。删除写tombstone且成员必须为空;旧投递不能复活,更高revision可以显式恢复。空项目可列出且asset_count=0,返回title/path。现有Drama项目实体revision不随所有子资源变化,不能直接充当快照revision;后续消费者须有事务outbox/完整成员投影与Media稳定ID映射。此处members是资源成员,不代表用户成员或团队ACL。
- 先添加失败测试,证明Drama合法internal项目快照可通过,而用户浏览器路径、错误账户/产品凭据、无授权、跨产品项目均被拒绝;旧版本、同版本冲突、删除及高版本恢复严格遵循上述合同。
- 核实Media项目索引支持的产品与正式字段,保持身份来源可信及产品对象责任;只开放完整合同,不以白名单改动冒充项目权限已经验证。
- 在上述固定Media基线同步开放项目目录、快照与显式project_app查询;必须执行真实隔离PG和受控HTTP签名验证,Platform合同fixture本身不等于双端通过。
- 运行相关controller/service测试,保存受控Media请求所见账号、产品、原项目版本及拒绝行为;更新契约和本机说明。
- 提交并独立评审;不接通生产Media或修改实际客户项目。
Task 3: 独立Go公共客户端及接入样例
Files: 新建platformclient/go.mod及包内client.go、identity.go、catalog.go、execution.go、materials.go、errors.go、types.go、*_test.go、README.md;提供方固定契约来源清单。补齐SDK依赖的机械契约:docs/openapi/platform-site-identity.fragment.json的SSO响应/Cookie/Origin说明、platform-account-assets.fragment.json的材料授权独立路径及两种worker授权、platform.json引用。router/platform_contract_test.go以具名POST材料授权映射识别实际wildcard dispatcher的正式显式合同,仍拒绝未知后缀或错误方法;不改变运行时路由。只修正本次接入范围的合同偏差。将新独立模块和两个样例接入既有Makefile、scripts/check-local.sh及.github/workflows/ci.yml中的backend检查,保留现有job/检查名、不增加新门禁;不改new-api根模块名或现有relaykit职责。
Interfaces: 独立模块github.com/Oceanway-AI/oceanway-platform/platformclient,Go版本沿现有最低1.25.1,优先标准库。NewClient接固定Platform origin、产品身份和服务凭据;每次调用分别提供SessionContext、ExecutionContext或MaterialContext,不能使用万能headers透传。类型由提供方合同维护,完整不规则media profile保留JSON,不复制业务计价;契约来源版本及全部本地ref摘要可验证。消费方不再复制提供方DTO;客户端保留已定义扩展数据,不把手写受限类型宣称为全量自动生成。
- 先写httptest失败测试:四类凭据允许集、受限Host/Origin、重定向不泄露、HTTP200 success:false、裸EXA、原生JSON/二进制、409价格过期、限长响应、context取消及未知提交不重试。
- 实现身份查询/退出及SSO挑战/授权/回调的服务端转发助手,明确配置允许的公开接收Host、传递实际Origin并保留多个Set-Cookie;SSO路径未接产品认证,不能用X-User-Origin替代Origin。不把sid当token或将客户端变为独立SSO服务器。登录UI继续Platform原入口。
- 实现全部适用模型目录和图片/视频消费预览,保留价格版本、规格、权益/钱包及allowed结果;不接受team payer后静默按个人执行。
- 实现EXA签发/释放、非流式文本原请求提交及恢复,以及保留原生取消语义的独立文本流式读取入口(不承诺稳定ID恢复、不自动重试);带Task 1稳定ID的媒体提交及恢复、Task/artifact/original manifest查询;请求正文使用调用方已冻结的原字节,禁止收费POST自动重试。明确区分HTTP结果和供应执行事实。
- 实现本人/worker材料授权与资源/项目操作,沿现有上传和Media代理合同;不向Media透传Cookie或Platform产品密钥。原件不在公共客户端自行下载重新存一份,不替产品决定采用或解绑。材料签发是裸JSON,项目与素材响应为原Media JSON;worker允许mat1或EXA二选一,account头只核对当前主体。为本次支持的命令提供明确字段/状态合同,未知扩展原样保留,不以泛型万能转发冒充已完成业务接入。
- 提供两个可编译的独立消费样例:studio与drama,复用同一module;使用固定本地契约夹具验证身份→目录→媒体预估→授权→稳定提交/恢复→原件引用链。样例不调用真实供应、不声称产品全量接入已完成。
-
GOWORK=off go test ./...、go vet ./...在独立模块通过;验证消费者不依赖new-api根模块;根仓go test不会自动包含嵌套模块,现有backend CI与本机检查必须显式覆盖该模块及样例。登记本地module版本/提交与发布方式,未发布tag不伪造可go get的版本。 - 提交并独立评审;将每项目需要填写的配置、固定产品ID、合同版本、现有局限和验收步骤交回docs。
完成与后续交接
三项逐项完成后,提供方形成可审查接入包。生产发布、公共module tag、真实重构项目升级与其业务回归另分别记录;不能用SDK夹具通过代替线上或产品集成通过。所有未覆盖团队/员工场景必须显式列出,继续交付其正式合同。运营界面在本域与公共前置具备后按PLAT-02-040推进。