补记Tripo图生3D图片引用提交预检口径
- 主规范明确图片引用解析分两步:提交时只做元数据预检,worker 执行时重新确认同一事实 - 主规范新增第 5 条验收标准,验收清单顺延至 12 条,里程碑同步引用范围 - 实施计划把图片输入预检写进固定执行顺序,并记录已改用定点引用查询取代宽查询 - 决策记录新增条目:站内引用禁止在提交路径读正文、调 provider 或列全量工程与素材库
This commit is contained in:
@@ -40,12 +40,12 @@ Milestone Spec: `docs/project-memory/plans/【里程碑】Tripo生成Worker执
|
||||
|
||||
3. **幂等提交路由**
|
||||
- 两个路由要求 Bearer 与 `Idempotency-Key`;复用现有外部生成幂等身份与 payload fingerprint,同键同请求返回原 operation,同键不同请求 409。
|
||||
- 执行顺序固定为:解析 JSON → 平台组合校验(含 provider 预检)→ 查价 → 入队;任何一步失败都在扣费与 provider 调用之前返回。
|
||||
- 执行顺序固定为:解析 JSON → 平台组合校验(含 provider 预检)→ 图片输入元数据预检(仅 image-to-model)→ 查价 → 入队;任何一步失败都在扣费与 provider 调用之前返回。
|
||||
- 验收:缺头 400、缺价格段 fail closed、同键重放不新增扣费。
|
||||
|
||||
4. **图片输入解析**
|
||||
- `source` 只接受站内资源或素材 ID;按分支校验归属并解析对象键,读出字节后上传 provider 换 `file_token` 再提交,不接受客户端直给 URL,也不把带签名的临时地址交给第三方。
|
||||
- 解析失败按 400 返回,不扣费、不入队。
|
||||
- `source` 只接受站内资源或素材 ID。提交时只做元数据预检(按 `source.kind` 定点校验归属、记录类型与对象键),worker 执行时重新确认同一事实,再读出字节并上传 provider 换 `file_token` 提交;不接受客户端直给 URL,也不把带签名的临时地址交给第三方。
|
||||
- 预检失败按 400 返回,不扣费、不入队;预检只按主键定点查引用,不拉取完整工程列表或素材库。
|
||||
- 验收:跨 owner 的资源 / 素材被拒绝。
|
||||
|
||||
5. **产物落库**
|
||||
@@ -70,6 +70,8 @@ Milestone Spec: `docs/project-memory/plans/【里程碑】Tripo生成Worker执
|
||||
|
||||
步骤 1 至 6 已落地:配置与路由、组合校验、定价、入队、图片输入解析、产物 OSS 写入与 worker 执行链路均已提交;步骤 7 的接线(`app.rs` merge、worker 分支、长任务超时)与文档同步也已完成。尚未完成的是需要真实环境的项:
|
||||
|
||||
- 图片输入在提交时已补元数据预检(`tripo3d::image_source::preflight_image_source`):按 `source.kind` 分支配对记录类型并复用既有定点引用查询 `resolve_editor_reference_record_by_id_for_owner`,取代原先“列工程 / 列素材库再筛”的宽查询;跨 owner、未登记、已删除与 `kind` 不符都在扣费与入队前返回 400,worker 执行时再重新确认同一事实。
|
||||
|
||||
- 默认配置里的 `model3d` 泥点定价数值仍未确认,缺段时提交按 fail closed 拒绝。
|
||||
- 没有跑过端到端真实调用(提交 → worker → OSS → 资源登记),现有证据只到 `cargo test -p api-server` 全绿(1085 通过)。
|
||||
- 新增的 `tripo3d/` 文件里,`storage.rs` 的完整字节写入、`artifacts.rs` 的完整字节读取都留着流式 TODO。
|
||||
|
||||
@@ -28,7 +28,7 @@ Implementation Plan: `docs/project-memory/plans/【实施计划】Tripo生成Wor
|
||||
|
||||
## 验收标准
|
||||
|
||||
主规范“验收标准”第 1 至 11 条全部满足,其中必须包含 text-to-model 与 image-to-model 各一次真实 Provider 调用与产物下载校验。
|
||||
主规范“验收标准”第 1 至 12 条全部满足,其中必须包含 text-to-model 与 image-to-model 各一次真实 Provider 调用与产物下载校验。
|
||||
|
||||
## 依赖
|
||||
|
||||
|
||||
@@ -8901,3 +8901,11 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
|
||||
- 上线依赖(本次未完成):`*.preview.genarrative.world` 通配证书(Let's Encrypt 通配只能走 DNS-01,域名在 DNSPod,certbot 无官方插件,需要 DNSPod API Token 配合 acme.sh)、station 侧按 Host 分发到 `84xx` 端口、dev 通配 vhost 与隧道;控制面本体需在 station 用 `scripts/deploy/preview-deployer-install.sh` 重建发布。
|
||||
- 验证:`cargo test -p preview-deployer-server`(13 项)、`apps/preview-deployer-web` vitest(13 项,含新增公网地址用例)、`npx tsc --noEmit`、`npm run preview-deployer:web:build`(`PREVIEW_DEPLOYER_WEB_BASE=/build/`)、`npm run check:preview-deployer`、`npm run check:encoding`、`git diff --check` 全部通过。
|
||||
- 关联文档:[开发运维](../../【开发运维】本地开发验证与生产运维-2026-05-15.md)、[Jenkins容器预览部署控制面技术方案](../../technical/【开发运维】Jenkins容器预览部署控制面技术方案-2026-08-15.md)。
|
||||
|
||||
## 2026-09-21 Tripo 图生 3D 的站内图片引用:提交时元数据预检,执行时重新确认
|
||||
|
||||
- 背景:图生 3D 的 `source` 只接受当前账号的画布资源 ID 或素材 ID,provider 需要的图片地址由服务端解析。首版实现把归属校验与解析都放在 worker 里,跨 owner / 未登记的引用会被正常受理、扣费、入队后才失败;且解析走的是「列全部工程 / 读素材库再筛」的宽查询。
|
||||
- 决策:引用解析固定分两步,提交与执行互不代替。提交时只做元数据预检:按 `source.kind` 分支要求解析结果与记录类型一致,复用既有定点引用查询 `resolve_editor_reference_record_by_id_for_owner`(SpacetimeDB 单事务按 owner + 主键解析项目资源或素材),不读图片正文、不调用 provider,失败即 400 且不产生 operation、不扣费。worker 执行时重新确认同一事实,通过后才读一次图片正文并上传换 `file_token`。跨 owner、未登记、已删除对外收敛成同一句不可用,不把「他人 ID 是否存在」变成可探测信息;`kind` 与实际记录类型不符单独报错,因为两个值都由调用方给出。
|
||||
- 边界:预检只按主键定点查引用,禁止拉取当前用户的完整工程列表或素材库,也禁止在提交路径上执行 provider 副作用(上传 `file_token`、submit)。该口径适用于所有「服务端站内引用 → provider 输入」的生成入口,Tripo 是首个按此收口的类别。
|
||||
- 验证:`cargo test -p api-server` 1085 通过(含新增的 `tripo3d::image_source` 源码钉住用例,断言预检与定点解析只调用窄查询、不含列工程 / 列素材库 / 读正文 / 上传);`cargo check -p api-server` 无 tripo3d 警告;`npm run check:encoding`、`node scripts/check-doc-index.mjs`、`git diff --check` 通过。真实 provider 端到端仍未跑。
|
||||
- 关联文档:[技术方案 Tripo 3D生成API集成](../../technical/【技术方案】Tripo 3D生成API集成-2026-09-21.md)、[实施计划 Tripo生成Worker执行链路与API路由](../plans/【实施计划】Tripo生成Worker执行链路与API路由-2026-09-21.md)。
|
||||
|
||||
@@ -49,6 +49,8 @@ source = { kind: "resource", resourceId } | { kind: "asset", assetId }
|
||||
|
||||
服务端按 ID 定点确认归属、解析出对象键后,从私有 OSS 读出字节并**上传 provider 换 `file_token`**,再以显式 `file_token` 提交生成任务:不把带签名的临时地址交给第三方,也不依赖 bucket 对公网可达。签名地址会在异步排队期间过期,且等于把私有桶的临时读取权外泄,因此不作为输入通道。
|
||||
|
||||
引用解析分两步,提交与执行互不代替:**提交时只做元数据预检**——按 `source.kind` 的分支做定点归属校验,确认记录类型与对象键存在,不读图片正文、不调用 provider,因此跨 owner、未登记、已删除与 `kind` 不符的引用都在扣费与入队之前返回 400;跨 owner、未登记与已删除对外收敛成同一句不可用,不泄漏他人 ID 是否存在,`kind` 与解析结果不符则单独报错(两个值都由调用方给出,不涉及探测他人数据);**worker 执行时重新确认同一事实**,通过后才读一次图片正文并上传换 `file_token`。预检只按主键定点查引用,不允许拉取当前用户的完整工程列表或素材库。
|
||||
|
||||
**结果落点**(两个端点都必填)使用 tagged enum:
|
||||
|
||||
```text
|
||||
@@ -182,13 +184,14 @@ width/height = 预览图像素尺寸
|
||||
2. 同一 `Idempotency-Key` 重复提交返回同一 operation,钱包只有一条扣费流水。
|
||||
3. 定价配置缺任一底价键时服务启动失败;请求命中 add-on 后扣费等于底价加全部命中 add-on;`fast` 与 `standard` 不加价。
|
||||
4. 组合校验前置于 provider 副作用:`texture=false` + `textureQuality`、`generateParts=true` 与 `texture=true` 的同现请求被拒绝且不扣费。
|
||||
5. worker 崩溃后重新 claim 不会产生第二次 submit:已有 checkpoint 的 job 只轮询、下载与落库。
|
||||
6. submit 成功但 checkpoint 写入失败的 attempt 终态失败且不自动重提。
|
||||
7. provider 成功但落库失败时 job 失败、该 attempt 退款,checkpoint 保留供对账。
|
||||
8. 完成结果按端点严格类型返回,只含模型与预览的正式资源引用,不含 provider task ID 与带签名的临时 URL。
|
||||
9. `assetLibrary` 分支产出 `assetId`;`projectResource` 分支产出 `resourceId`,且 `assetKind=model3d`、`AssetObject.content_type` 为模型 mime、`content_length` 与实际对象一致。
|
||||
10. 真实 Provider smoke 覆盖 text-to-model 与 image-to-model 各一次,下载字节数与 `Content-Length` 一致。
|
||||
11. 定向测试、`cargo check`、`npm run check:spacetime-schema`、`npm run check:encoding`、`node scripts/check-doc-index.mjs`、`git diff --check` 全部通过。
|
||||
5. image-to-model 的 `source` 元数据预检前置于扣费与入队:跨 owner、未登记、已删除与 `kind` 不符的引用返回 400,不产生 operation、不扣费,也不把图片正文读进内存或调用 provider。
|
||||
6. worker 崩溃后重新 claim 不会产生第二次 submit:已有 checkpoint 的 job 只轮询、下载与落库。
|
||||
7. submit 成功但 checkpoint 写入失败的 attempt 终态失败且不自动重提。
|
||||
8. provider 成功但落库失败时 job 失败、该 attempt 退款,checkpoint 保留供对账。
|
||||
9. 完成结果按端点严格类型返回,只含模型与预览的正式资源引用,不含 provider task ID 与带签名的临时 URL。
|
||||
10. `assetLibrary` 分支产出 `assetId`;`projectResource` 分支产出 `resourceId`,且 `assetKind=model3d`、`AssetObject.content_type` 为模型 mime、`content_length` 与实际对象一致。
|
||||
11. 真实 Provider smoke 覆盖 text-to-model 与 image-to-model 各一次,下载字节数与 `Content-Length` 一致。
|
||||
12. 定向测试、`cargo check`、`npm run check:spacetime-schema`、`npm run check:encoding`、`node scripts/check-doc-index.mjs`、`git diff --check` 全部通过。
|
||||
|
||||
## 未决问题
|
||||
|
||||
|
||||
Reference in New Issue
Block a user