OceanWay 单体运行时与旧站退役任务包
Task ID:
OCEANWAY-RUNTIME-CUTOVER-01状态:LOCAL_IMPLEMENTATION_CANDIDATE / NOT_PRODUCTION_MIGRATED / NOT_DEPLOYED当前隔离实现 Base SHA:3daafc09a7aaed090c43d23bca9f535b2da22c77
目标结果
oceanway-vozeb 的 Next.js/React 应用成为唯一 OceanWay 产品和运行时:用户在
oceanway.tech(后续也包括解析到同站的 ocean-way.top)使用同一套登录、Session、
用户、Key、积分/账本、套餐、用量、创作与管理后台。模型执行只通过管理员配置的
new-api 网关,应用不直接管理 new-api 后方的渠道、账号池或模型调度。
旧站与旧 sub2api 只作为一次性只读迁移源。切换后停止旧站登录、Session、账本和业务 写入并关闭服务;新站不保留旧站运行时依赖,也不建立 Retail Portal Session、双登录或 Identity Bridge。
本任务明确取代 VOZEB-RETAIL-NEXT-KEY-MODEL-USAGE-01 中“Retail 是运行时事实源”和
“Retail Portal Session Bridge”的方案。该旧文件只保留为历史决策记录,不能再指导实现。
已确认契约
- 新登录只签发
oceanway_session;旧 Session 不迁移、不读取,用户首次进入新站重新 登录。迁移的 bcrypt 密码允许在本项目验证,成功后按现有机制渐进重哈希。 - 用户、旧 Key、余额/冻结额、套餐/订阅、订单和用量历史均需迁移;每条源数据必须有 ID Map、状态、Manifest、Checkpoint、Checksum 和例外记录,重复 Apply 不得增加经济 价值或重复数据。
- Key 运行时由本项目持有 HMAC 与独立加密密文;列表只显示摘要,当前用户显式请求单
Key 时才可返回完整值,响应
no-store,不得进入日志、URL 或浏览器持久存储。 - 金额、积分、额度和历史成本使用 PostgreSQL
numeric与十进制字符串。旧单位到新 积分的映射在正式 Apply 前单独冻结;未冻结时只能保留原精度快照,不能猜测换算。 /models读取本项目管理员维护的逻辑模型与已就绪绑定;只公开 OceanWay 模型 ID、 能力、参数和积分摘要,不暴露 Channel、Group、上游账号或内部模型映射。/keys、/models、/usage最终只调用同源/api/developer/**,不再调用/api/retail/portal/**。- VOZEB 只保留 LICENSE、NOTICE、第三方许可证和上游来源等法律记录;用户可见 Logo、 文案、Cookie、元数据、导航、导出文件名和业务契约统一为 OceanWay。
- 余额、钱包合计、套餐积分等摘要默认显示两位小数;数据库、迁移、追加式流水、单笔 API
消费与退款保留八位小数。单笔非零金额不得因为小于
0.01而显示或结算成0.00。
实现切片
R0:身份与模型运行时(本轮)
- Cookie 切换为
oceanway_session,登录/注册/退出主动清除旧 Cookie; - 新建
/api/developer/models,直接读取本地逻辑模型与 new-api 渠道配置; /models改用 OceanWay 本地契约;- 固定后续 Schema、迁移和退役边界,不连接真实旧库、不部署。
R1:本地 Key 域(本地候选已实现,尚未迁移/部署)
- 新建正式用户 Key 表、Repository、Service 与
/api/developer/keys; - 支持 list/create/reveal/revoke,所有权、HMAC、AES-GCM、限流和
no-store完整; /keys移除 Retail adapter。
实现与安全证据见 OCEANWAY-DEVELOPER-KEYS-R1.md。R1 只完成新站自身 Key 运行时,
不代表旧 Key 已导入或真实用户已验证。
R2:本地用量与经济域(用量/Key/公开网关已形成候选)
- 已建立
/api/developer/usage,以当前 Session 用户查询网页积分流水和已导入的旧站历史 用量;旧站成本使用LEGACY_CREDIT,不冒充当前积分; /usage已移除 Retail adapter,旧/api/retail/portal/**运行时已退役;- 迁移 Apply 可把旧 Key 同时写入正式 Key 表,原值可按新 HMAC 认证和显式取回;
- 余额 opening entry、显式套餐映射、只读历史订单投影已在隔离 PostgreSQL 合成用户上完成 首次 Apply、重复 Apply 与 fingerprint Verify;原密码登录、Key 列表/取回、余额、套餐和 历史用量 API 已实测通过。
- 已新增公开
/v1/models与文本/图片/音频/视频创建入口;旧 Key 可按原值鉴权,调用经后台 逻辑模型映射进入同一积分消费、失败退款和用量归属链路。用户 Key 不会转发到上游;同一 幂等身份不会再次生成或重复扣费。 - PostgreSQL 积分字段、迁移 opening、消费和退款保留八位小数;界面余额汇总显示两位,个人 中心单笔流水和开发者用量保留最多八位。
- 仍需冻结非零冻结余额政策、旧非终态订单增量责任,以及公开异步任务轮询/取消契约。
实现与边界证据见 OCEANWAY-DEVELOPER-USAGE-R2.md。
R3:迁移器与生产切换
- 在合成数据完成
audit → dry-run → apply → verify → repeated-apply; - 获得单独授权后只读旧库,冻结源、备份、最终增量、校验和、例外处理;
- 新站冒烟和账本核对通过后关闭旧站写入与服务,DNS 指向同一 OceanWay 站点;
- 生产数据访问、导入、部署、DNS 和旧服务关闭均需当次明确授权,不包含在 R0。
今晚切换 Go / No-Go
旧服务在以下全部检查为 GO 前保持在线且可回退;任何一项未知或不一致均为 NO-GO:
| 检查项 | GO 条件 | 当前状态 |
|---|---|---|
| 用户身份 | dry-run 的 password:reset-required=0,或已批准并演练逐用户恢复方案;active/disabled 数量与源一致 | 待真实只读审计 |
| 可用余额 | 用户逐条 opening、总额、负余额和八位小数 fingerprint 一致;重复 Apply 不增加余额 | 合成库通过,真实库待审计 |
| 冻结余额 | frozen-balance:nonzero=0,或已明确映射为独立不可用资产且完成解冻/退款流程 | 待真实只读审计 |
| 套餐/订阅 | 每个旧 Group 都有显式 plan map;subscription:unmapped=0;重叠订阅逐条保留 | 待映射与真实 dry-run |
| Key | 每把有效旧 Key 原值可通过 /v1/models 与代表性生成调用;停用、过期、IP、RPM、并发状态不被放宽;旧 quota/used 逐 Key 核对单位 | 合成库通过,真实 Key 待抽样 |
| 用量历史 | 行数、用户归属、Key 归属、Token/成本聚合和 fingerprint 一致,页面可查询 | 合成库通过,真实库待审计 |
| 订单 | 所有非终态订单逐条列出责任方;新站不重复履约、退款或接管半条流程 | 待真实 dry-run |
| 模型网关 | 生产 new-api 代表性文本/图片/音频/视频成功,失败精确退款,上游与内部地址不泄露 | 本地夹具通过,真实网关待验收 |
| 反向代理 | VOZEB_PRO_TRUSTED_PROXY_HOPS 与真实代理层数一致,Key IP 规则不能被伪造转发头绕过 | 待生产配置 |
| 回滚 | 目标库备份可恢复;旧站保持只读/可恢复;观察窗口内账本差异可定位 | 待 Operations 演练 |
迁移 dry-run 现在输出完整 classifications,包括密码兼容、账号、冻结/负余额、Key 状态/
过期、API/网页用量、套餐映射和非终态订单计数。订阅 dry-run 会完整列出未映射数量,Apply
仍对任一未映射订阅失败关闭。
R0 允许修改路径
AGENTS.md
.env.example
docs/oceanway/OCEANWAY-RUNTIME-CUTOVER-01.md
docs/content/docs/progress/todo.mdx
docs/content/docs/progress/pending-test.mdx
CHANGELOG.md
web/src/lib/auth/session.ts
web/src/lib/auth/session.test.ts
web/src/integrations/oceanway/**
web/src/lib/server/developer-model-service.ts
web/src/lib/server/developer-model-service.test.ts
web/src/app/api/developer/models/**
web/src/services/api/developer/**
web/src/app/(user)/models/page.tsx
web/src/app/(user)/models/page.test.tsx禁止修改 retail-platform、真实旧库、生产环境、DNS、支付、现有创作执行逻辑和管理员
渠道写入逻辑。R0 只复用管理员已经配置的渠道和逻辑模型,不发起真实模型调用。
R0 验收
pnpm --dir web exec vitest run src/lib/auth/session.test.ts src/lib/server/developer-model-service.test.ts src/app/api/developer/models/route.test.ts src/app/'(user)'/models/page.test.tsx --config vitest.config.ts --reporter=dot
pnpm --dir web exec tsc --noEmit --pretty false
pnpm --dir web exec eslint <R0 files> --quiet
pnpm --dir web run build
git diff --check必须证明:旧 Cookie 不被读取;新登录签发 OceanWay Cookie;模型 API 要求当前 OceanWay
Session;只公开可解析的本地逻辑模型;响应不包含渠道、密钥或上游模型;筛选、分页、
音频能力和 no-store 正常。正式迁移与停服不以 R0 自测结果代替。