文档
08_归档04_VOZEB任务卡

VOZEB Retail Next:Key、模型、用量三域最小任务包

Task ID:VOZEB-RETAIL-NEXT-KEY-MODEL-USAGE-01 状态:LOCAL_IMPLEMENTATION_CANDIDATE / CANDIDATE_EVIDENCE / NOT_FORMAL_TEST runtime authorization:LOCAL_CANDIDATE_IMPLEMENTATION_GRANTED(用户已明确要求后续仅在 oceanway-vozeb 的 Next.js/React 项目继续实现;本文件仍不代表正式 Testing、发布或生产授权)

1. 基线与事实源

项目固定值
唯一 UI/运行时基座VOZEB-PRO Next.js App Router + React 19
clean base SHAdb32a44b25b55d3d04ea6f8e7e5ac00596b87fef
base tree19b66e73c923dac90f960986a70f453bcb5aebc4
上游来源VOZEB-PRO v0.0.6 / 4de8360f46b3b8e9a76649ec68b6ae3d028345ac
Retail 参考/Users/wangzihao/Projects/retail-platform(只读;不 cherry-pick、不改写)
Retail 契约入口contracts/portal.openapi.yaml 的 Keys、Catalog、Usage 章节
页面/产品参考Retail OWPDOC-04-003_Page_List.md(只读产品事实)

所有页面、组件和 Next 服务器代码均从上述 VOZEB clean base 产生。retail-platform 只提供产品规则、公开 DTO、错误和端点事实;其 Vue 运行时、Pinia、Vue Router、旧页面 壳和旧视觉均不迁入 VOZEB。Retail 仍是用户、公开模型、Key、用量和账务事实源;浏览器 不得直连 Retail 或任何上游,统一经过 VOZEB 的 server-only BFF/typed adapter。

2. 目标用户结果

在 VOZEB 现有首页、Canvas、媒体和其它能力保持不变的前提下,登录用户可以:

  1. 在 /keys 查看脱敏的通用 API Key、创建 Key、按一次明确的本人操作取回单个完整 Secret,并立即删除/失效 Key。
  2. 在 /models 查看已发布且可用的公开模型,按能力筛选并阅读公开参数/价格摘要; 页面不显示 Channel、Group、供应商账号或内部绑定。
  3. 在 /usage 查看带筛选、排序和分页的零售用量,在 /usage/:requestId 查看一条 自己拥有的请求的生命周期、计量、资金分摊和对账状态。

这三个域是只读或用户自有凭据操作;不在本任务内实现新的生成、扣费、商品、订单、 钱包、Canvas、媒体或管理后台行为。

事实映射(仅作为候选追踪入口):K-01 对应 KEY-P0-001、KEY-P0-002、 KEY-P0-003、KEY-P0-004;M-01 对应 MOD-P0-001;U-01 对应 BILL-P0-003。这些映射不提升 Retail 事实域的 Design/Development/Testing/Operations 状态,正式追踪仍以各自登记册为准。

3. 前置决策(未确认前停在候选)

  • 会话:推荐 Retail Portal Session 为唯一业务身份,由 VOZEB server-only BFF 代持 HttpOnly Cookie;VOZEB 本地 session 只能作为 UI hydration,不得形成双登录或 按邮箱猜测映射。当前候选默认拒绝未完成的 Identity Map/Session Bridge;仅当 OCEANWAY_RETAIL_SESSION_BRIDGE_MODE=local-cookie-fixture 且 Gateway 为 loopback 合成服务时,才允许注入测试 Cookie;生产进程强制禁用该模式。正式接入前必须先固定 服务端映射、失效同步和审计规则,并更新本任务包。
  • 公开契约:GET /portal/v1/models 没有独立 detail endpoint;第一版只做目录列表 和列表内快照。GET/PATCH /portal/v1/keys/{key_id} 在当前契约中标为 reserved, 不擅自实现;Key 第一版只使用明确列出的 list/create/reveal/delete。
  • 金额/用量:Decimal 以字符串穿过 BFF、React state 和 UI;禁止用浮点计算。用户 界面只展示图片次数、积分及其它公开计量单位,不展示人民币、法币或内部 USD; retail_cost/final_consumption 仅作为服务端契约字段保留,不能直接渲染。

4. 三个最小垂直切片及顺序

K-01:通用 Key(首个运行时切片)

端点:

  • GET /portal/v1/keys:只返回脱敏元数据;
  • POST /portal/v1/keys:创建并在响应中短暂返回 Secret;
  • POST /portal/v1/keys/{key_id}/secret:仅当前用户明确请求的单 Key Secret;
  • DELETE /portal/v1/keys/{key_id}:立即失效并保留历史用量事实。

页面结果:/keys 列表、空态、创建表单、创建成功一次性提示、显式复制/再次取回、 删除确认、active/disabled/expired、未登录/无权限/服务不可用状态。

安全不变量:Secret 不进入 URL、LocalStorage、SessionStorage、普通日志、分析事件、 列表/详情 DTO 或批量响应;Secret 读取响应必须 Cache-Control: no-store,服务端只按 当前会话和 Key 所有权取回。

M-01:公开模型目录

端点:GET /portal/v1/models?capability=&limit=&offset=。

页面结果:/models 列表、能力筛选、分页、搜索/空态、不可用/服务异常状态;只展示 PublicModel 的公开字段。模型选择器可复用同一份已校验目录,但不能在浏览器解析 Auto、 选择渠道或推导价格。

明确缺口:没有冻结的模型 detail endpoint,因此 /models/:id 暂留为后继任务;不 通过读取全量目录伪造 detail API。

U-01:用量报告与请求详情

端点:

  • GET /portal/v1/usage:日期、model、key、source、status、q、sort、limit、offset;
  • GET /portal/v1/usage/{request_id}:用户范围内的生命周期、requested/actual usage、 meter items、funding 和 reconciliation。

页面结果:/usage 列表/聚合/筛选/分页,/usage/:requestId 详情;展示 created/reserved/dispatched/settled/released/reconciliation_required 等真实状态, 不提供重试、退款、再次执行或下游诊断。

顺序固定为 K-01 → M-01 → U-01:Key 先建立凭据与会话安全边界;模型目录再为 统一 Agent 的公开能力选择提供事实;用量最后依赖稳定的 request、model、key 标识和 服务端计量事实。三切片仍可分别审查和独立验收;当前候选为便于在 VOZEB 中复核而收口 为同一组边界文件,不扩展为其它跨域功能。

5. 允许修改路径(仅限本任务)

以下是候选实现的精确白名单;未列出的文件不得因“顺手接线”修改。

边界与服务端 BFF

web/src/integrations/retail/contracts.ts
web/src/integrations/retail/endpoints.ts
web/src/integrations/retail/key-client.ts
web/src/integrations/retail/catalog-client.ts
web/src/integrations/retail/usage-client.ts
web/src/integrations/retail/index.ts
web/src/integrations/retail/*.test.ts
web/src/lib/server/retail-runtime-transport.ts
web/src/lib/server/retail-adapter-factory.ts
web/src/lib/server/retail-route-response.ts
web/src/lib/oceanway/retail-gateway.ts
web/src/lib/oceanway/retail-gateway.test.ts
web/src/lib/server/retail-runtime-transport.test.ts
web/src/lib/server/retail-adapter-factory.test.ts
web/src/lib/server/retail-route-response.test.ts
web/src/app/api/retail/portal/keys/route.ts
web/src/app/api/retail/portal/keys/[keyId]/route.ts
web/src/app/api/retail/portal/keys/[keyId]/secret/route.ts
web/src/app/api/retail/portal/models/route.ts
web/src/app/api/retail/portal/usage/route.ts
web/src/app/api/retail/portal/usage/[requestId]/route.ts
web/src/app/api/retail/portal/route.test.ts

key-client.ts 只承载 Key 的字段白名单、所有权/Secret 响应约束和命令映射; catalog-client.ts、usage-client.ts 只承载公开 DTO 解析与查询归一化。Transport 必须 集中执行 Retail origin(生产仅 https://api.ocean-way.top,本地仅 loopback fixture)/path、 HTTP method、Cookie 范围、Request ID、响应大小和错误分类校验;Route Handler 不得复制 业务规则或直接访问数据库。Usage client 与 Portal 复用正的时间窗、366 天上限及未来五分钟 边界,避免把明显无效查询发送给上游。

页面、同源客户端与左侧导航

web/src/services/api/retail/keys.ts
web/src/services/api/retail/models.ts
web/src/services/api/retail/usage.ts
web/src/services/api/retail/http.ts
web/src/services/api/retail/index.ts
web/src/app/(user)/keys/page.tsx
web/src/app/(user)/models/page.tsx
web/src/app/(user)/usage/page.tsx
web/src/app/(user)/usage/[requestId]/page.tsx
web/src/components/layout/app-sidebar.tsx
web/src/constant/navigation-tools.ts
web/src/constant/navigation-tools.test.ts

页面只调用同源 /api/retail/...,不读取 Cookie 或内部 Token。导航只在既有左侧栏中 增加“模型广场 / API 与密钥 / 用量”;不新增顶部菜单,不修改 Foundation 材质、背景、 Canvas、Create、Media 或 Drama 视觉文件。/models/:id、Key metadata GET/PATCH 和 任何 /api 页面别名不在本次白名单内。

候选文档与证据

docs/oceanway/VOZEB-RETAIL-NEXT-KEY-MODEL-USAGE-01.md

实现候选若产生测试/发布记录,必须在独立授权任务中另行更新 progress、Testing 和 Operations 事实源;本文件不能替代正式 OWTEST-* 或 OWOPS-* 结论。

6. 明确禁止修改与非目标

  • apps/user-web/**、apps/admin-web/**、任何 .vue、Pinia、Vue Router 或 Vue bridge;
  • Retail 参考仓库的 cmd/**、internal/**、migrations/**、contracts/** 和真实服务;
  • VOZEB Foundation/Canvas/Create/Assets/Drama/Media/Commerce/Billing/Admin 业务文件;
  • web/src/lib/server/billing*、web/src/services/api/points.ts、VOZEB 本地 points/账本、 provider/channel/new-api/sub2api 直连或 AI 执行路由;
  • 数据库表、迁移、真实用户/旧库/生产网络、真实模型调用、支付、部署和远程推送;
  • 为模型目录增加内部绑定、渠道探测、Auto 决策或手写价格;
  • 为 Usage 增加重试、退款、重跑、后台调账或把下游 Request ID 作为公开字段。

本任务不把“VOZEB 其它能力直接继承”解释为可以继承其重复的身份、points、账务或 provider 事实;只继承现有页面壳、组件和创作能力,三域数据仍走 Retail 公开边界。

7. 验收矩阵(候选阶段)

自动检查

cd web
pnpm exec vitest run src/integrations/retail src/lib/server/retail-* src/app/api/retail src/app/'(user)'/keys src/app/'(user)'/models src/app/'(user)'/usage --reporter=dot
pnpm exec tsc --noEmit --pretty false
pnpm exec eslint src/integrations/retail src/lib/server/retail-runtime-transport.ts src/lib/server/retail-adapter-factory.ts src/app/api/retail src/app/'(user)'/keys src/app/'(user)'/models src/app/'(user)'/usage --quiet
pnpm exec next build
git diff --check

必须证明的用户结果

域关键断言
Key列表永不含完整 Secret;创建/显式取回只针对当前用户单 Key;no-store;删除后立即失效;窄桌面无溢出
模型只显示 available 公开模型;能力筛选和分页沿用服务端;不出现 Channel/Group/内部模型;空/异常/无权限可恢复
用量Decimal 不经浮点;用户界面只展示次数/积分/公开单位而不展示法币;筛选、排序、分页和详情 ID 绑定当前用户;生命周期/资金/对账状态完整;404 不泄露所有权
共通同源 BFF、Cookie 不可由 JS 读取、Request ID 透传、键盘/焦点可用、390/430 与桌面布局、reduced-motion/无网络状态

浏览器回归必须使用本地 TCP fixture 或合成 BFF,不得调用真实 Retail、旧库、支付或 上游。实现者自测不能将状态提升为 IMPLEMENTED/VERIFIED/OPERATIONALIZED;需由独立 Testing/Operations 任务基于固定候选构建复核。

8. 当前候选证据

代码候选提交为 9c4c0f76f0df3fdb34cb8a6c0db78f6977169bdc,基于 db32a44b25b55d3d04ea6f8e7e5ac00596b87fef,工作树在验证后保持 clean。当前证据仅证明 本地候选可构建和可回归,不提升正式事实域状态:

  • 定向 Retail 边界测试:11 个文件、50 个断言通过。
  • 完整 VOZEB Vitest:522 个文件通过、4 个文件跳过;2363 个断言通过、9 个跳过。
  • TypeScript、ESLint、Prettier、依赖安全审计通过;Next 隔离生产构建 66/66 页面通过, Standalone 产物 151 个静态文件、15 个公开资源完整。
  • Chromium 本地 Foundation/Home 回归:9/9 通过;仅使用本地合成安装流程,未访问真实 Retail、旧库、支付或上游模型。
  • retail-platform 与 VOZEB 主工作区均未写入;本候选只存在于 oceanway-vozeb-next-migration 工作树。

仍未覆盖或未授权的事项:正式 Identity Map/Session Bridge、真实 Retail 会话、完整 Testing/Operations 验收、移动端正式性能基准、Usage 全量筛选/导出、模型详情、Key 轮换和 生产部署。当前页面在没有 loopback 合成 fixture 时会安全地显示“尚未完成 Retail 账户绑定”, 不会猜测 VOZEB 用户与 Retail 用户的对应关系。

9. 停止条件、交付和回滚

遇到会话方案未定、OpenAPI 字段冲突、Key Secret 可能泄露、Decimal 精度无法保持、 需要改 Go/数据库/Provider、需要真实网络或需要修改 Foundation 时,立即停在 CANDIDATE_EVIDENCE,回报具体冲突;fixture 只可用于 loopback 合成验证,不能静默替代 正式 Identity Bridge 或真实服务。

候选交付必须记录:每个切片的 base_sha、变更文件、契约版本、测试原始结果、未覆盖 状态和回滚 commit。回滚仅撤销该候选 commit,不得 reset 或清理共享工作树。正式运行时 接入前,必须由用户/事实域 Owner 重新确认本任务包并另发具名开发授权。

On this page