Files
atlas-seller-kit/docs/product/ozon-first-publish-review-plan.md
2026-09-30 15:57:54 +08:00

119 lines
24 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 编辑页 Ozon 首次上架:字段对齐、开发方案与实施记录
> 2026-09-30:产品决策已确认,首期代码已实现;真实店铺 VAT 与七牛图片交付验收待完成。现行接口以 `docs/api/product-editor-and-publishing.md` 为准,下文保留字段研究与实施方案供追溯。
## 1. 目标和首期边界
编辑页底部将当前禁用的「选择 SKU 并首次上架」替换为两个入口:
| 入口 | 建议行为 |
|---|---|
| **上架至 OZON** | 只校验并提交当前平台、目标店铺下状态为 `not_listed` / `failed` 的活动 SKU;已成功导入的 SKU 保留原记录、不重复提交,并在确认摘要中逐项说明已跳过的 SKU。任一待提交 SKU 或商品级字段未通过预检,本次一个也不提交。 |
| **部分上架** | 打开 SKU 选择窗口,仅可选择当前商品下 `not_listed` / `failed` 的活动 SKU;至少选择 1 个,只校验并提交选中的 SKU。`submitting` 和 `imported` 展示状态、原因提示,但不可勾选。 |
这是**首次导入 Ozon 商品卡片**,不是更新已导入商品,也不包含库存设置。Ozon 的 `imported` 表示商品资料已导入;审核、前台可见性和可售库存需以在线商品同步与后续库存能力为准。按钮文案按需求使用“上架”,结果页须明确显示“已导入 / 待审核 / 不可售”等平台事实,不能把 `202` 或 Ozon `task_id` 当作上架成功。
首期沿用当前 Ozon `rFBS` 商品发布配置;`fbs`、`fbo`、`fbp` 的仓库、条码与库存规则另行验收。在当前首期中,不向 Ozon 提交仓库或库存。首期不发布视频、视频封面、富内容,也不借此入口修改已导入商品。
一次首次上架最多提交 **50 个 SKU**,包括“上架至 OZON”自动选出的待提交集合和“部分上架”手选集合;超过 50 个时先提示用户分批使用“部分上架”,不自动拆批或静默截取前 50 个。Ozon 接口本身允许的数量更高,但首期按本产品决策收紧。
## 2. 官方接口核对(2026-09-30)
本次直接核对 Ozon 官方 Seller API 页面及其 OpenAPI 2.1 定义:
1. [创建或更新商品 `POST /v3/product/import`](https://docs.ozon.ru/api/seller/zh/#operation/ProductAPI_ImportProductsV3):一次最多 100 个 `items`;返回 `result.task_id`,仍需查询任务。它同时是**更新**接口,因此首次上架不能仅凭 HTTP 200 推断新建成功,也不能盲目重试不确定的提交。
2. [查询导入状态 `POST /v1/product/import/info`](https://docs.ozon.ru/api/seller/zh/#operation/ProductAPI_GetImportProductsInfo):按 `task_id` 返回各 `offer_id` 的 `product_id`、`status`、`errors`。官方列出的 item 状态是 `pending`、`imported`、`failed`、`skipped`;`skipped` 不能直接等同首次导入成功。
3. [按标识符查询商品 `POST /v3/product/info/list`](https://docs.ozon.ru/api/seller/zh/#operation/ProductAPI_GetProductInfoList):可按 `offer_id` / `product_id` / `sku` 查询,单次总计最多 1000 个;返回 `statuses.moderate_status` 等审核、验证和可见状态。用于提交前货号归属检查、超时后的对账及导入后的状态同步。
4. [类目属性 `POST /v1/description-category/attribute`](https://docs.ozon.ru/api/seller/zh/#operation/DescriptionCategoryAPI_GetAttributes) 与[类目树](https://docs.ozon.ru/api/seller/zh/#operation/DescriptionCategoryAPI_GetTree):类目 / 类型及必填、SKU 维度、字典属性以平台当前目录为准。Atlas 已有平台级目录缓存和发布预检,发布任务继续复用它们。
5. [商品操作限额 `POST /v4/product/info/limit`](https://docs.ozon.ru/api/seller/zh/#operation/ProductAPI_GetUploadQuota):按门店检查创建/更新额度;导入接口的 429 还可能带 `Item-Retry-After` 和 `Item-Rate-Limit-Remaining`,Worker 应尊重重试时间。
评审时提供的毛子 ERP 请求体顶层是 `product_id`、`form_data`、`is_online`,`form_data` 中含 `shop_id` 和 `skus`,整个请求体未出现 `vat`。它是 ERP 接收编辑表单的请求形状,不是 Ozon `/v3/product/import` 所需的顶层 `items[]` 形状;仅凭这一份请求,无法判断 ERP 服务端是否补上 VAT、调用了另一个 Ozon 接口,或采用了其他处理。
**VAT 文档存在版本冲突,不能再称为已确认必传**:同一 `v3ImportProductsRequestItem` 的 Ozon 官方 [俄文 OpenAPI](https://docs.ozon.ru/api/seller/swagger.json) 和[英文 OpenAPI](https://docs.ozon.ru/api/seller/en/swagger.json)的 `required` 均只有 `description_category_id`、`price`、`type_id`、`offer_id`,`vat` 是可选属性;[中文 OpenAPI](https://docs.ozon.ru/api/seller/zh/swagger.json)则将 `vat` 列为必填。这三份文档均标为 2.1,不能凭语言版本判断真实店铺校验结果。俄文与英文说明将 `vat: "0"` 定义为“该商品不征收 VAT”,并未声明“不传 `vat`”的默认行为;也未找到明确规定“中国主体、跨境 rFBS”一律应传哪个值的 Ozon 官方说明。[Ozon Global 跨境合同](https://global-help.ozon.com/contracts-for-sellers/dogovor/)区分 Ozon 服务费 VAT 与交易适用税款,也没有给出导入字段的固定税率。中国出口环节的增值税处理不能直接推导此商品字段的值。
**现有整理稿需要在评审后订正**:`docs/integrations/ozon-seller-api/04-product-import.md` 写了 `offer_id` 最长 255、图片最多 15、顶层 `description`、以及“重复货号必定 409”;官方当前导入定义分别是**最多 50 字符、最多 30 张图片、描述不在 item 顶层字段、同一导入接口同时承担创建和更新**。旧整理稿列出的 `processing`、`moderation` 也不是当前 `/v1/product/import/info` 的 item 状态;审核状态另从商品信息接口读取。按本次产品决策,**编辑草稿改为货号最多 50 字符、Ozon 发布标题最多 500 字符、每 SKU 最多 30 张图片**,与 Ozon 当前导入接口一致;来源商品标题等采集证据不因发布标题上限而改写。已有超长草稿需提示用户修正,不自动截断或静默改写。
## 3. Atlas → Ozon 字段映射
| Ozon `items[]` 字段 | Atlas 来源与适配 | 发布时校验 |
|---|---|---|
| `offer_id` | 当前目标店铺下该 SKU 的 `listing.offer_id`,原样作为卖家货号 | 草稿和 Ozon 当前接口均最多 50 字符;现存超长值在编辑页显示并要求用户主动修正,保存 / 上架均不自动截断。本店数据库唯一,并查询 Ozon 当前店铺同货号是否已存在。 |
| `name` | 通用模式取 SPU `profile.title`;按 SKU 设置模式取当前 SKU 标题 | 草稿与 Ozon 当前接口均最多 500 字符;俄文标题不可为空。SKU `display_name` 不作回退。 |
| `description_category_id`, `type_id` | 当前平台活动叶子类目缓存对应的 Ozon 数值 ID | 均有效;schema 和实际使用字典通过现有 `publish-preflights` 定向刷新。 |
| `price`, `old_price`, `currency_code` | SKU 已确认报价的售价 / 划线价;币种来自目标店铺 | 保留十进制字符串精度;`price > 0`;仅 `old_price > price` 时传 `old_price`;报价仍与当前采购、包装、店铺、类目和履约匹配,币种与店铺 Ozon 账户一致。 |
| `vat` | 当前模型缺字段;中、俄、英文官方 schema 对是否必传有冲突。对已确认的中国主体、跨境 rFBS 店铺,首期拟**省略字段**,不擅自填 `"0"` 或俄罗斯境内税率;若该店铺确有适用税率,以卖家或 Ozon 支持确认值为准。 | `"0"` 在俄/英文定义中是“不征收 VAT”,不是“省略”;省略后 Ozon 是否补默认值尚无官方结论。测试店铺须做一次真实导入,查询任务结果与 `/v3/product/info/list` 返回的 `vat`,确认可接受且结果符合店铺税务设置后再开放生产发布;若被拒绝或结果不符,暂停该店铺发布并由卖家确认税率,不自动重试成 `"0"`。 |
| `depth`, `width`, `height`, `dimension_unit`, `weight`, `weight_unit` | 每个 SKU 合并继承后的**包装**长宽高与物流重量;首期统一 mm/g | 均为已确认的正整数,不能拿商品本体尺寸或净重替代;每个 item 独立解析。 |
| `images` / `primary_image` | 当前 SKU 已保存的素材 ID 及顺序;首期用 `images` 首张作为主图,不另传 `primary_image` | 草稿最多 30 张,现有迁移 `031_sku_image_limit.sql` 已把数据库顺序上限扩至 30,与 Ozon 当前数量上限一致。发布时从正式素材生成 Ozon 可访问的公网 HTTPS JPG/PNG 地址;WebP 需生成 JPG/PNG 发布派生图或给出可定位的阻断项。 |
| `barcode` | 当前只有 SPU 通用条码 | rFBS 首期允许不传;不得把同一个通用条码复制给多个 SKU。需要按 SKU 条码或 FBP 发布时,先扩充数据模型和校验。 |
| `attributes[]` | 类目动态属性中已确认的通用值复制到本次各 SKU,`is_aspect=true` 的值只取当前 SKU;主要信息字段依固定 Ozon ID 映射 | `id` / `complex_id` 转数值;字典值以官方 ID 及缓存文本构成 `dictionary_value_id` / `value`,文本值构成 `value`。仅提交当前类目活动属性,强制项和最大值数沿用最新 schema。 |
| `complex_attributes` | 首期无视频或复杂富内容输入 | 无值时省略或空数组;不虚构。 |
现有固定属性绑定是品牌 `85`、型号 `9048`、商品类型 `8229`、标签 `23171`、富内容 `11254`、简介 `4191`。发布适配器应只在当前类目 schema 确认这些 ID 可用时映射:品牌、型号、有效的 SKU / SPU 标签与描述进入对应属性;`type_id` 已在顶层时不重复拼装 `8229`。这些 ID 目前来自 Atlas 的绑定实现;**在发布适配器编码前应以目标类目的实时属性响应验证值类型、字典约束与可用性**,不能仅靠旧示例。中文对照、中文商品名、采购价、货源备注不进入 Ozon 请求。
部分上架后只锁定**当前商品的型号 `common.model`**:任一 SKU 首次导入成功,后续草稿保存不得改动型号;前端禁用并解释原因,服务端在保存事务内核对已导入 SKU 后拒绝绕过页面的修改。型号对应 Ozon 属性 `9048`,后续新 SKU 沿用锁定值。品牌、描述及其他动态属性仍可修改并保存在 Atlas 草稿中;这些编辑不会自动更新已导入的 Ozon 卡片。若其他共同属性变化可能影响新 SKU 与旧卡片合组,发布预检给出差异提示,但不以“共同属性不可改”为由阻断草稿保存。
## 4. 页面流程与验证语义
1. 点击任一按钮时先检测编辑页脏数据。若有未保存修改,走现有带版本检查的保存草稿流程;保存失败或资料版本冲突时停止上架,并定位字段。之后以**服务端已保存快照**作为唯一发布输入。
2. 「上架至 OZON」只选当前平台下未成功导入的活动 SKU;已导入 SKU 不传给预检或发布接口,在确认摘要中展示其名称 / 货号及“此前已导入,本次未重复提交”的原因。正在提交的 SKU 另提示“提交处理中”,本轮不重复排队。若没有可提交 SKU,不创建 job。「部分上架」先展示 SKU 名称、货号、状态及就绪问题供勾选;已导入 / 正在提交的 SKU 不可选择,服务端遇到过时选择仍按现有 `SKU_ALREADY_IMPORTED` / `SKU_IMPORT_IN_PROGRESS` 拒绝。
3. 调用现有 `publish-preflights`,只针对本次提交集合检查。`refreshing` 显示目录刷新中并使用同一 SKU 集合重试;`blocked` 显示 SPU 与每个选中 SKU 的字段问题,禁止创建 job;`ready` 才展示最终确认摘要(店铺、类目、SKU 数、货号、价格、无库存说明)。
4. 用户确认后使用新的幂等键创建 `publish-jobs`。服务端在同一事务重新校验版本、店铺、SKU 状态、目录与字段并固定请求快照;前端先前的 `ready` 不作为授权凭证。
5. 返回 202 只表示任务已排队。页面轮询 job,展示逐 SKU `排队 / 提交 / 等待 Ozon / 已导入 / 失败`,保留 Ozon 的脱敏错误字段,允许用户修改失败 SKU 后重新发起新任务;已导入的绝不由此入口再次提交。
6. 任一入口都不静默剔除被选中的无效 SKU。一次 Ozon 调用可能出现逐 SKU 成功和失败,UI 按 item 结果汇总,不能把整批简单标成成功或失败。
已导入 SKU 的提示建议为:**“以下 SKU 已在当前店铺导入,本次未重复提交:{SKU 列表}。需要修改时,请到「在线商品」查看,并在 Ozon 后台处理。”** 列表过长时显示数量、前几项和展开入口。目前 `docs/api/online-listings.md` 定义的在线商品功能只有查看和同步,不能把按钮写成可直接跳转到 Atlas 在线商品编辑。只删除 Atlas 的采集箱或本地上架记录,不会删除 Ozon 商品,也不能据此开放再次导入;后续若实现平台删除与重上架,应单独设计安全的状态转换。
目前 `GET validation` 的总 `ready` 是“全部未导入 SKU 就绪”的汇总;部分上架应以所选 SKU 的 `publish-preflights.validation` 为准,不复用无选择范围的页面总标记。即使现行 `publish-preflights` 允许最多 100 个,本功能也应在页面、预检及创建 job 的服务端边界统一实施 **1–50 个 SKU** 的上限;超过 50 个时提示“本次最多上架 50 个 SKU,请使用「部分上架」分批提交”,不截取、不自动拆批。
现行 `docs/api/product-editor-and-publishing.md` 第 3 节还明确留下“类目树过期时如何保护真正发布”的待决项。创建 job 前需确定是否强制刷新整棵类目树;无论采用哪种策略,必须再核对所选类目仍在目标平台有效,不能只依赖编辑页先前看到的类目状态。
## 5. 服务端任务、媒体与失败恢复
- `POST /api/product-platform-profiles/{profile_id}/publish-jobs` 和 `GET /api/product-publish-jobs/{job_id}` 沿用现有预留路径;请求、响应和错误码先更新 `docs/api/` 与 `@atlas/contracts` 后实现。创建接口必须使用 `Idempotency-Key`,只接受当前工作空间、平台、profile 和店铺下的 SKU。
- 新迁移将 `product_publish_jobs`、`product_publish_job_items` 从架构草案落到真实数据库,补齐 `workspace_id`、复合外键、RLS、唯一约束、索引和可恢复的状态字段。与 listing 状态变更、Outbox 事件在同一事务提交;BullMQ 只传 job ID,不带密钥、商品全文或图片地址。
- Worker 读取加密保存的当前目标店铺 Ozon 凭据,按固定快照组装单批最多 50 个 item 的请求;在提交前批量查询远端 `offer_id`,避免 `/v3/product/import` 将外部已有同号商品当作更新。收到 `task_id` 后持久化,再轮询 `/v1/product/import/info`;`imported` 记录 `product_id`,`failed` 保存脱敏错误,`skipped` 先对账。商品审核与库存从 `/v3/product/info/list` 及在线商品同步单独读取。
- 网络超时或 Worker 崩溃时,先根据已存 `task_id` 或 `offer_id` 向 Ozon 对账;不确定请求是否已到达时不能直接重发导入请求。429 遵守官方重试头;5xx 有界退避;确定性 4xx 转成逐 SKU / 整批失败并保留可修复原因。重复 Outbox 消息与同幂等键请求不得重复上报。
- 已保存的 SKU 图片不是外部图片链接:采集图会先下载并转存 Atlas 对象存储,网络导入、用户上传和图片处理结果也存为正式素材;编辑草稿只保存 `asset_id` 和顺序。API 当前签发的 `preview_url` 是指向 Atlas 对象存储的**10 分钟预览凭证**,不随草稿持久化。不能直接把它当发布图片 URL,因为 Ozon 可能在链接失效后抓取,且本地默认对象存储 endpoint 为 `http://localhost:9000`,外网无法访问。
- 发布前需从这些 Atlas 正式素材提供**公网 HTTPS、可在 Ozon 异步抓取期间持续访问**的 JPG/PNG 图像交付链路;推荐专用不泄露桶 key 的随机访问 URL,绑定素材版本,可撤销并在任务完成后留合理抓取宽限期。发布快照存 asset ID / 版本,不持久化临时预览 URL 或密钥;WebP 转换在 Worker 中完成并验证实际公网可抓取性。生产对象存储端点及其公网可访问性尚需部署配置确认,不能从本地默认值推断生产环境一定不可访问。
- SKU 的历史首次导入 `offer_id` 和 `product_id` 锁定;已导入 SKU 的 Atlas 草稿编辑仍不隐式更新 Ozon。在线商品镜像保留其独立同步事实。
### 七牛 Kodo 图片交付调研结论
项目既有架构已选定本地 MinIO、共享测试与生产七牛 Kodo。七牛官方[私有资源下载](https://developer.qiniu.com/kodo/1656/download-private)文档定义私有资源的 `e`(秒级 Unix 过期时间)和 `token` 下载凭证,过期返回 401;[Node.js SDK](https://developer.qiniu.com/kodo/sdk/nodejs)提供 `privateDownloadUrl(domain, key, deadline)`;[自定义源站域名](https://developer.qiniu.com/kodo/8556/set-the-custom-source-domain-name)支持绑定 HTTPS 证书。因此**七牛支持给正式素材签发指定有效期的 HTTPS 私有下载地址**。这确认能力存在,尚不等于现有生产域名、证书、跨境抓取及 Ozon 异步抓图均已验收。
发布适配器应从 `media_asset` 的 bucket / object key 在提交前生成**独立于 10 分钟页面预览**的七牛下载 URL;对象存储 S3 API endpoint 继续用于上传与内部读取,给 Ozon 的 URL 使用已绑定的公网 HTTPS 下载域名。七牛的[S3 兼容服务域名](https://developer.qiniu.com/kodo/4088/s3-access-domainname)也支持 HTTPS,但其文档要求 AWS Signature,不能把该服务域名当成匿名图片地址。URL 有效期设为可配置、覆盖提交排队、Ozon 抓取和重试的窗口;具体时长及过期后 Ozon 是否再次抓图,必须在测试店铺做真实导入与延迟抓图验证。若平台需要长期稳定可抓取 URL,再评审专用发布副本 / 域名方案,不能凭文档推定签名短链永久足够。
当前若干素材入库路径仍将 `storage_provider` 写死为 `local_minio`,与已选定的生产七牛架构不一致。实施七牛联调前,应让入库记录按环境填写实际 provider,并验证从已有 `media_asset` 到正确下载域名的映射;不得仅把对象存储 endpoint 换成七牛地址就宣称发布图片可用。
实施时已更新 API 第 7 节:快照固化素材 ID / checksum / 存储身份,Worker 提交时签发独立 URL;每个 job 对应一个最多 50 SKU 的 Ozon task,混合成功失败汇总为 `partially_succeeded`。
## 6. 实施顺序与验收
| 阶段 | 修改范围 | 交付与验收 |
|---|---|---|
| A. 契约与数据 | `docs/api/`、`packages/contracts/`、`packages/database/migrations/` | 将 VAT 标为待目标店铺验证的可选适配字段,首期不因文档分歧强加必填税率配置;修订上架契约及旧 Ozon 整理稿;草稿约束改为货号 50、标题 500、图片 30,并处理历史超长草稿;建 job/item 表、索引/RLS;迁移可在空库与现有库运行,跨工作空间和同商品归属测试通过。 |
| B. 服务端快照与预检 | `apps/api/src/product-editor/` | 同一 SKU 集合重算目录和字段;草稿保存与发布预检均对超过 50 字符的货号给出定位提示,并校验价格、图片、型号锁定、已上架状态和每批 50 个上限;VAT 按已验证店铺策略省略或传已确认值;冻结逐 SKU 适配快照和 Outbox;并发、版本冲突、重复键、远端同货号用集成测试覆盖。 |
| C. Ozon Worker | `apps/worker/src/`、媒体交付模块 | 组装可验证的真实请求体,单批 ≤50 提交 / 轮询 / 对账 / 超时恢复;修正素材 provider 写入与下载域名映射,使用七牛公网 HTTPS 下载域名和可配置签名有效期;用固定夹具比对导入字段,模拟混合成功失败、`skipped`、429、进程重启和重复投递;在测试店铺验证跨境抓图和延迟抓图。 |
| D. 编辑页 | `apps/web/src/pages/products/`、`apps/web/src/services/` | 两个按钮、部分上架选择弹窗、保存→预检→确认→任务进度与逐 SKU 错误;全部上架跳过并列出已导入 SKU,待提交项有错则无 job;超过 50 个提示分批;首个 SKU 成功后型号不可改,其他草稿属性仍可编辑。 |
| E. 联调验收 | API / Worker / Web / Ozon 测试店铺 | 使用同类中国主体跨境 rFBS 店铺验证省略 `vat` 的真实导入、任务结果及 `/v3/product/info/list` 返回值,并与卖家店铺税务设置核对;未通过前不开放生产发布;再覆盖单 SKU、全部 SKU、部分 SKU、同 SPU 后续补上架、类目字典过期、图片抓取、Ozon 拒绝、超时重试、店铺货号冲突;typecheck/build 和受影响测试全部通过。 |
## 7. 评审时需确认的产品决策
1. **全部上架与已导入 SKU(已确认)**:只提交 `not_listed` / `failed`;已导入 SKU 保留并在摘要列出跳过原因,正在提交的 SKU 也不得重复排队。
2. **草稿长度(已确认)**:货号 50 字符、Ozon 发布标题 500 字符、每 SKU 图片 30 张,与 Ozon 当前导入限制对齐;旧超长值需人工修改。
3. **VAT(产品决策已确认,目标店铺联调待验证)**:中国主体、跨境 rFBS 的首期在导入 item 中省略 `vat`,不自动填 `"0"`;需以同类测试店铺真实导入和商品信息返回值验收省略后的行为,再开放生产发布。如果 Ozon 校验要求传值,或返回结果与卖家店铺税务设置不符,再由卖家向 Ozon 确认适用值并补店铺级配置;此时不得用默认 `"0"` 绕过。毛子 ERP 表单省略 `vat` 仅是参考,不能证明其发往 Ozon 的内容。
4. **多 SKU 条码与履约(已确认)**:首期仅 `rFBS`,可不传条码,不把 SPU 通用条码复制到多个 SKU;不在这次提交库存或仓库。
5. **每批数量(已确认)**:最多 50 个待提交 SKU;超出即提示使用部分上架分批操作,不自动拆批。
6. **部分上架后的型号(已确认)**:任一 SKU 成功导入即锁定 `common.model`;其他草稿属性可修改,但不会隐式更新 Ozon 已导入商品。
7. **图片交付(方案已确认,联调待验收)**:使用七牛私有正式素材的独立签名下载 URL,过期时间可配置,公网 HTTPS 域名与页面预览地址分离;生产域名 / 证书、Ozon 可抓取性、签名有效期以及 WebP 转码结果要在测试店铺验证。
2026-09-30:维护者确认 VAT 决策并授权按本方案开始开发;生产发布仍须完成 VAT 与七牛图片真实联调验收。
## 8. 本轮实施与验证
- 已实现两个入口、指定 SKU 预检、确认摘要、原子 job/item/Outbox 创建、请求幂等、冻结快照、远端货号检查、异步导入轮询及不确定提交对账。任何待提交项校验失败都不会创建批次;任一素材准备失败则本批剩余项全部失败、不发导入请求。
- 实际请求显式列出允许字段,省略 `vat`、条码、库存、仓库与顶层描述;金额保留十进制字符串。成功后锁定型号与历史货号,进行中禁止换店;完成后仍允许换店,已导入 SKU 保留原店铺事实。
- 图片校验 checksum、复制独立发布对象、WebP 转 JPEG;七牛私有 URL 默认 7 天,`OZON_IMAGE_URL_TTL_SECONDS` 可配置(至少 1 小时)。原有 MinIO 素材需迁移到七牛后再交付,不能仅改 provider 标签。
- 迁移 `055` 已在空白隔离库和本地开发库验证应用。API/编辑器/素材 26 项与 Worker 14 项测试通过,contracts/API/Worker/Web 类型检查与构建通过。浏览器使用隔离数据库验证全部选择、部分禁选、缺字段阻断、确认摘要、创建与刷新恢复;未调用真实 Ozon 导入。
- 生产 `OZON_PUBLISH_ENABLED=auto` 默认关闭。仍需配置七牛 S3 存储、HTTPS 下载域名与签名凭据,并在同类测试店铺验收 VAT 省略行为及延迟抓图,再显式启用生产上架。配置见根目录 `.env.example`。