文档
03 平台02 platform04_开发

PLAT-04-015 Go服务统一接入指南

多仓Go服务接入Platform的配置、会话、模型预估、执行恢复和统一资源合同及无真实生成验证步骤

本页是各重构项目共同使用的提供方接入说明,实施范围见PLAT-04-014。各服务保留自己的React前端、Go业务、PostgreSQL数据及Redis命名空间。公共客户端在Platform仓独立发布,业务仓无需合并,也不导入new-api根模块。

接口、客户端制品和生产部署按同一批具名验收记录核对;本文的配置示例不代表现网已经启用。消费方必须使用实际存在的不可变模块版本,不能引用不存在的远程tag。个人接入、团队付款与员工运营委托分别验收,不能用个人权限模拟后两者。Drama消费方实施见DEV-DRAMA-04-001,具体源码、合成验收、已部署Platform/Media制品、已发布SDK、Drama实际运行与明确验收限制集中记录于PROC-02-024,不以本指南的存在宣称整链已发布。

1. 一条接入链与四种凭据

凭据用途接入责任
用户会话Cookie用户身份、产品目录、预估、签发受限授权仅在当前浏览器会话路径使用,session.sid不能替代Cookie token
产品凭据识别可信Go产品服务及允许动作只在服务端保存;不能单独指定任意用户消费
EXA后台原生模型执行及原任务读取服务端保存,与原业务任务关联;worker不携带Cookie、Origin或用户Authorization
mat1与会话撤销约束关联的材料委托worker使用mat1或EXA其中一种;不能直接发给Media

Platform重新为Media签名。产品无需Media共享签名密钥、供应商密钥、对象存储密钥或桶权限。素材账户头只用于核对已认证账号,不能选择另一个账号。

当前业务产品ID为studio、drama、commerce。Creative是各平台共用的画布与Agent基座,不是Studio的别名:承接Studio、Drama、Commerce业务时分别保持对应产品身份、凭据及业务对象范围。产品上下文由可信服务配置和已校验对象确定,不能让浏览器任意选择密钥,也不能把全部调用改成creative。新增业务产品ID需要提供方扩展正式注册范围。运营员工动作不能通过伪装产品用户实现。详见Creative共享基座与产品身份边界。

2. Platform部署方准备

正式环境使用PostgreSQL受限角色和Redis。以下仅列配置名和占位值,实际值进入部署秘密配置:

OCEANWAY_PLATFORM_ENABLED=true
OCEANWAY_PLATFORM_VALIDATION_ENABLED=false
SQL_DSN=postgresql://ROLE:SECRET@PG_HOST:5432/PLATFORM_DB?sslmode=verify-full
REDIS_CONN_STRING=rediss://:SECRET@REDIS_HOST:6379/0
SESSION_SECRET=INJECT_STABLE_RANDOM_SECRET
CRYPTO_SECRET=INJECT_STABLE_RANDOM_SECRET
OCEANWAY_PLATFORM_IDENTITY_CONFIG_FILE=/run/secrets/platform-identity.json
OCEANWAY_MEDIA_ASSETS_ORIGIN=https://media.example.com
OCEANWAY_ASSET_SIGNING_KEY=INJECT_SHARED_PLATFORM_MEDIA_SECRET
  • Platform正式模式要求显式PostgreSQL URL和受限数据库角色;LOG_SQL_DSN留空或与SQL_DSN一致,不能把审计/账务拆到另一数据库。媒体消费约束要求同一数据库句柄;独立LOG_DB句柄即使指向同库也不受支持,应在预留或派发前以503 consumption_storage_unavailable、no_execution拒绝,不可用分别提交两套事务绕过。
  • Redis配置后启动执行PING;未配置时源码仍可能继续运行,进程启动不能作为Redis已启用的证据。
  • 多节点保持稳定一致的会话/加密秘密,不照抄上游示例值。正式Media origin为纯HTTPS origin;共享签名秘密至少32字节,仅Platform与Media持有。
  • Model Connections、产品发布目录、有效价格及原生TaskAdaptor准入由Platform配置。身份可用、目录可读和实际供应生成可用是不同检查项。

配置和启动约束以源码仓docs/platform-bootstrap.md、docs/local-development.md及实际部署手册为准,不为本次接入另造启动、迁移或生产发布入口。

产品凭据注册

OCEANWAY_PLATFORM_IDENTITY_CONFIG_FILE指向普通JSON文件,权限0600、大小不超过64 KiB,未知字段会被拒绝。示意内容:

{
  "cookie_domain": "example.com",
  "cookie_name": "oceanway_session",
  "allowed_origins": [
    "https://console.example.com",
    "https://admin.example.com",
    "https://studio.example.com"
  ],
  "return_origins": [
    "https://console.example.com",
    "https://studio.example.com"
  ],
  "products": [{
    "key_id": "studio_go_v1",
    "product": "studio",
    "secret": "INJECT_UNIQUE_RANDOM_SECRET_AT_LEAST_32_CHARACTERS",
    "actions": ["model:invoke"],
    "origins": ["https://studio.example.com"]
  }]
}

启动时现有SyncPlatformProductKeys登记凭据;正式请求头为X-Platform-Product-Key: key_id.secret,不能只传secret。该scope覆盖本批模型目录、EXA/native和材料worker接入,不需要为新链额外开放旧run:*。

管理端现有查看和撤销接口要求identity:manage,没有对外创建/轮换凭据的HTTP接口。已有key_id不能换secret或product;修改配置也不会自动更新已有key的actions/origins。部署方按现有受控流程登记新key、核对后切换消费方,再撤销旧key,不能把编辑配置当作原key已完成轮换。

3. 登录、Host和Cookie

同Cookie域的产品可沿用Platform登录页,回调严格为产品origin下/platform/login/complete;通过GET /api/platform/v1/auth/login-return预检。回调origin必须在return_origins内。当前Studio的next白名单不能推广为任意产品URL白名单,其他产品在自身会话中保存允许的返回位置。

跨注册域SSO challenge → authorize → callback要求由真正承载已注册callback的提供方receiver接收请求。部署方配置additional_domains和精确sso_callbacks,回调路径固定/api/platform/v1/sso/callback;callback返回JSON,产品再决定业务页跳转。不存在将common Console API请求改写为产品Host即可代理SSO的合同;产品proxy在不同APIOrigin下明确返回501,跨域SSO须单独验收。

  • Session.Host只用于验证真实产品入口,必须来自可信入站请求及部署白名单。出站HTTP Host与TLS目标始终来自APIOrigin/LoginOrigin实际URL的authority,绝不能覆盖为产品Host,也不能用伪造Forwarded头模拟。真正SSO receiver按其实际Request.Host验证会话域;真实Origin、nonce Cookie及全部Set-Cookie按对应合同保留。
  • login-return请求完全省略Cookie与Origin头,不能设置为空字符串:present-empty不等于absent。其他非issuer请求仍保留调用方实际提供的非空Origin,不将该窄例外扩展为全局清空来源。
  • SSO路由没有产品鉴权中间件,不能以X-User-Origin代替Origin。已通过产品鉴权的其他会话写操作才允许受控X-User-Origin;两者同时存在时必须一致。
  • Cookie名称可配置;不要在客户端固定默认名称后丢失会话。多个Set-Cookie必须逐条传回浏览器,不使用共享Cookie Jar吞掉或混用用户会话。
  • cookie_host与__Host-模式只允许指定主机;不能用它实现兄弟产品域共享Cookie。
  • 退出沿用Platform撤销与清Cookie合同,不仅清产品本地状态。产品自身缓存必须响应401及真实身份鉴权403,不能继续把旧身份当有效授权。资源委托权限拒绝的403须与会话失效区分:提示资源同步受限,已有内容仍按产品ACL访问;真实401仍清除身份。
  • 已验证主体与会话分别作为前端命令/草稿范围;只由最新被接受的bootstrap提交身份,切换会话清除旧反馈与命令授权。旧会话的迟到响应不能覆盖新身份。材料委托由当前浏览器会话以真实Origin取得,按到期时间续期,切换会话取消旧续期及回填;worker只保存受限委托,不保存用户Cookie或Origin。

4. 固定Go模块与请求上下文

独立模块为github.com/Oceanway-AI/oceanway-platform/platformclient,最低Go版本沿提供方1.25.1。模块固定Platform origin、产品身份和服务凭据,每次调用分别使用会话、执行或材料上下文,不接受浏览器传来的万能headers。

Creative承载多个业务产品时,可按可信注册表维护分别固定产品与凭据的客户端;不随页面修改同一实例身份。任务、Agent会话、资源引用和恢复记录均保持原业务产品。现有单产品客户端与样例不等于共享Creative已完成多产品接入,专项验收见DEV-X-01-008。

消费方固定已发布的不可变模块版本;本地开发可以临时使用workspace或replace,但发布候选必须脱离本机绝对路径构建。契约来源、完整本地引用闭包及摘要随提供方客户端维护;不只固定入口platform.json而让fragment随HEAD漂移。

客户端负责传输、凭据、错误与恢复合同。提供方保留身份、实时权限、计价、钱包和退款权威;产品保留对象ACL、业务状态、候选采用与业务持久化。费用、价格版本和不规则模型profile不能被消费方另算或截断。

公共方法按凭据边界使用:

接入工作客户端入口
当前身份、退出、跨域登录Identity、Logout、LogoutAll、SSOChallenge、SSOAuthorize、SSOCallback
全模型目录、图片/视频消费预览Models、PreviewMedia
后台授权生命周期IssueExecution、ReleaseExecution、RevokeExecution
原生执行与恢复SubmitText/RecoverText、StreamText、SubmitMedia/RecoverMedia
原任务及原件身份Task、Artifacts、Original;内容读取另用具名方法
当前用户与后台材料IssueMaterial、CurrentMaterials、WorkerMaterials;资源与绑定使用各自具名方法,PutProject仅限worker

NewClient配置固定Origin、Product、ProductKey和允许的会话Host/Origin。SessionContext从可信入站请求取得Host、Origin与Cookie;其中Host只验证入口,不改变出站URL authority或TLS目标。login-return按上节完全省略Cookie和Origin;ExecutionContext只携带EXA,MaterialContext只选mat1或EXA。返回的Response.AppendCookies逐条追加Set-Cookie。不要共用HTTP Cookie Jar存储不同用户的会话。

Result[T]提供已知字段的类型投影,Response.Body保留有界完整原JSON;重新序列化Data不能保证保留未知扩展。原生响应不强套Platform信封。默认错误文本只含状态与类别;原始诊断正文包含私有数据,不写入普通日志。

独立模块本地验证与发布

在Platform源码仓根目录运行:

make check-platformclient

该入口核对完整契约快照,并对platformclient、platformclient/examples/studio及platformclient/examples/drama三个独立Go module执行test/vet/build。两个样例使用本地replace和明确的开发占位版本,只连接受控本地夹具。它们验证同一SDK调用链,不代替产品的持久化worker或React页面。

每个模块也可独立运行GOWORK=off go test ./...、go vet ./...及go build ./...,不导入new-api根模块。提供方常规检查和既有backend CI显式纳入这些嵌套模块,避免根目录测试漏检。

客户端随包携带contracts/manifest.json及完整本地引用闭包,固定源码基线、Media合同来源和逐文件SHA-256;交付提交另见验收记录。发布者完成版本审查后,按嵌套模块规则打platformclient/vX.Y.Z标签;消费方固定实际已发布版本。当前可安装版本为github.com/Oceanway-AI/oceanway-platform/platformclient v0.1.0-rc.2,标签platformclient/v0.1.0-rc.2;完整提交、校验和与部署事实见PROC-02-024。rc.1在Drama首次部署中暴露HTTP Host覆盖缺陷并触发安全回滚,不作为可生产版本;rc.2已包含真实TLS多vhost回归修复,Drama实际4ac5运行制品与匿名登录200核对、原生浏览器下载未通过及已登录浏览器证据阶段限制见PROC-02-024。产品域SSO proxy对不同APIOrigin明确返回501;正式支持Console共享Cookie登录,不能视为跨域SSO或14域全功能验收。样例中的本地开发占位版本不等于消费方发布版本。

5. 模型选择与费用预估

  1. 当前会话与产品凭据获取GET /api/platform/v1/products/{product}/models。返回该主体及产品全部适用模型,包含文本;不以产品私有静态清单替代。
  2. 生成表单使用media_generation_profile;usage_schema描述计费用量,不能当成同一份参数表单。
  3. 图片/视频调用POST .../media/consumption-preview,携带冻结的模型、规格、预计用量和价格版本,处理allowed、权益/钱包分配及价格变化。该路径为只读预览,不保留资金。
  4. 文本正常执行和计费,不新增文本费用预估展示。预估不等于最终账单,生成准入仍由Platform重新校验。

用户确认后冻结同一模型与规格对象的价格版本、消费方式billingPreference及每项钱包上限walletMaxPoints。默认消费方式为wallet-fallback;未另设显式上限时,消费上限取确认预览的精确walletPoints十进制字符串,包括"0",不能改用更高的钱包余额或预览允许上限。若提供显式上限输入,确认页应显示并冻结用户确认值。金额不得转为浮点数再序列化。

多规格批量逐项预览、逐项确认上限,再沿各自稳定请求提交;公共规格可复用单项预览,但上限仍逐项冻结,不能按数量伪造总钱包/权益预览。参数或报价变化使旧确认失效;已受理项不重发,失联仅恢复原命令与冻结正文,不在派发前重新报价并静默抬高上限。用户侧使用分镜序号、规格、精确上限与中文消费方式,价格版本和内部ID保留于请求/审计,不作为确认文案。

SDK与提供方原生执行必须共同强制这些约束;消费预览与原生钱包计费一致、价格版本及钱包上限在真实提交处生效,是发布前置。不能仅在前端或消费方校验后就认定提供方已完成资金约束,实际版本和具名验收结果见对应过程记录。

公开price-estimate只提供价格计算,不能替代用户实际消费资格预览。当前消费预览和EXA为个人上下文,不接受team payer后静默回落个人;团队合同按对应工作包交付。

6. 原任务提交和失联恢复

产品先在自身数据库持久化业务任务及稳定请求ID,再签发/保存EXA。后台模型请求使用原生协议和已冻结原始字节;媒体带X-Platform-Media-Request-ID,非流式文本使用既有X-Platform-Text-Request-ID。这两个ID不是供应商任务ID。

场景处理
首次媒体POST正常返回保持原生响应,持久保存X-Task-ID及原业务关联
首次响应丢失、进程重启使用原EXA与稳定请求ID读取GET /internal/relay/media-requests/{request_id}
相同ID与相同请求再次POST返回原任务回执,不重新准入/计费/派发
同ID改变正文、协议、路径或有效query409冲突,不能借同一身份发起另一生成
恢复返回not_found或UNKNOWN保留未知事实,不自动重发、不自动退款
task_available=true表示原Task可查询,不表示生成成功或原件已可交付
原件保存失败恢复原任务和资源引用,不能重新生成

媒体恢复回执版本为oceanway.media-request.v1,与首次原生响应分别解析。HTTP成功、供应受理、生成完成、结算完成、产品保存成功为不同事实。multipart正文和Content-Type boundary必须保持;客户端不对收费POST做自动重试。

流式文本使用独立原生流入口,保留取消和实际计费语义;不把非流式稳定请求恢复的保证套用于SSE,不自动重试已开始的流。

EXA过期/释放后的原任务GET/HEAD沿现有读取政策,仍受当前产品和账户授权约束。产品不能保存用户Cookie作为长期worker授权,也不能用新EXA伪造同一原任务。

7. Media资源与项目快照

原生Task的artifact original接口返回oceanway.assets.v1不可变manifest,包含Media稳定asset/version/file身份。产品保存这些身份及自己的业务引用,不把一次性访问地址当资产ID,不把原件再次下载到自己的桶作为接入流程。

项目快照仅经PUT /internal/materials/projects/{project_id}写入。身份和app来自可信授权,正文为title/path/revision/deleted/members;members是Media资源的asset_id/version_id,不是用户成员。现行服务要求title/path/revision;省略deleted默认false,省略或空members代表完整替换为空成员,绝不是保留旧成员。消费方应显式提交完整快照。

Drama精确项目链接为/creative/drama/steps/1?projectId=<encoded project_id>。低revision是成功但不更新,同revision同正文幂等、异正文409;删除写入空成员tombstone,更高revision可显式恢复。空项目允许asset_count=0。

Drama当前实体revision不会随全部子资源改变,业务asset/version/file也不是Media ID。实际消费必须补独立快照序列、事务outbox、完整资源成员投影及Media ID映射。不能只投当前采用版本而意外释放仍需保留的历史资源。

容量与引用权威留在Media,政策留在Platform。客户端不硬编码默认容量,不因架构统一改变既有待遇。团队素材、员工跨账号访问不在个人接入合同中;没有授权就不能通过改account头实现。

8. 接入验收顺序

使用明确的测试环境和合成账号,保留接口状态、合同版本及脱敏结果:

  1. 核对Platform制品和正式模式;部署方单独证明PostgreSQL受限角色、Redis启用及Media签名配置,/api/status不能替代这些检查。
  2. 验证无会话401、正确会话身份、错误Host/重复Cookie拒绝、登录返回白名单、退出撤销和浏览器Cookie属性。
  3. 验证正确产品目录、错误产品/撤销凭据拒绝,保留完整模型profile和价格版本。
  4. 做图片/视频消费预览及过期价格版本检查,确认没有创建付费任务或保留资金;再用受控原生供应和隔离账务验证精确每项钱包上限(包括零)与消费方式在实际提交处生效,拒绝后不得派发收费。
  5. 读取本人materials storage/projects,验证Platform→Media签名与账号隔离;不需生成或上传。
  6. 在测试环境签发并释放EXA/mat1,验证凭据允许组合;该步骤写授权状态,但不调用模型。
  7. 使用受控供应夹具和隔离PG验证原请求恢复、并发去重、原件manifest与项目引用;真实模型联调和生产发布单独记录。
  8. 产品完成自身业务ACL、事务outbox、任务恢复和页面回归后,才登记该产品接入完成;SDK样例通过不能替代产品验收。

每个项目接入时填写同一张交接表:产品ID、消费仓/提交、SDK固定版本、Platform合同/制品、允许origin/callback、密钥标识(不含secret)、资源同步责任、验收证据和未覆盖范围。

On this page