视觉按最新原型,业务按已确认PRD。现有代码为满足设计而改造。执行见按设计实施与任务卡;技术增量和文档复审不等于产品完成。
Dramivio 消费者与后台边界复审
复审日期:2026-10-03。独立复审只修改本报告与本地复现工具,没有修改业务源码、发布服务或连接生产数据库。
本轮发现 1 个 P1、3 个 P2。作者修复后,四个问题均完成独立复测并关闭。这个结论只覆盖当前邮箱身份、消费者查询、配置发布和 App 凭据边界,不代表额度、邀请、离线缓存等后续模块已完成。
发现及复测
| 级别 | 问题 | 修复后的独立复测 |
|---|---|---|
| P1 | Payload 公开首个用户注册绕过管理员权限 | 空库与删除最后管理员后均返回 403;公开请求没有创建用户;可信本地初始化仍能创建管理员 |
| P2 | 部分渠道展示统一版本的总集数 | 统一版本共 3 集、选中渠道仅 1 集时,返回 episodeCount=1、canonicalEpisodeCount=3 |
| P2 | 配置发布与查询快照创建并发,旧条件仍能分页 | 在快照插入前暂停请求、发布新标签含义后恢复,请求返回 409 invalid_cursor |
| P2 | 退出前的迟到 SDK 会话响应恢复旧登录 | 模拟退出失败与迟到续期响应,本地 Cookie 始终为空,旧会话结果返回 credentials_changed |
P1:公开首个用户注册
位置:短剧库/services/admin/src/config.mjs:43。
在已迁移但没有管理员的隔离数据库上,匿名调用官方 REST 入口 POST /api/admins/first-register,提交邮箱、密码及 role=admin。修复前返回 200,随后保存用户端配置和发布均返回 200;预期的可信初始化反而被已有用户阻止,返回 409。
原因是 Payload 的首个用户注册操作使用 overrideAccess=true,同时绕过集合创建权限和角色字段权限。框架默认行为不能仅靠 access.create 限制。
现在 admins 集合显式覆盖公开 /first-register,返回 403 bootstrap_required。使用同一个官方 handleEndpoints REST 入口和真实 PostgreSQL 复测:空库拒绝、公开创建数量为 0;可信 bootstrapAdministrator 创建成功;删除最后管理员后公开注册仍拒绝。
P2:渠道集数与版本集数混用
位置:短剧库/services/platform/src/catalog.mjs:151。
将渠道 B 的 1 集,经明确的集数映射,合并到渠道 A 的 3 集版本。仅授权渠道 B 的查询在修复前返回 B 的播放入口,却展示 3 集,后两集无法通过该入口播放。
现在查询按选中渠道的 source_episode 数量返回可播集数,另用 canonicalEpisodeCount 表达统一版本总集数。独立真实数据库复测得到 1 与 3,两个含义分开。
P2:发布与快照插入竞态
位置:短剧库/services/platform/src/catalog.mjs:126。
修复前,查询先读旧标签含义和匹配结果,在快照插入前暂停;后台把同一标签 ID 从 love 改为 action 并发布、删除已有快照;恢复查询插入后,旧游标仍能继续返回 Love,而新查询已经返回 Action。
现在快照复用既有配置 revision,续页校验版本,并在返回前再次检查发布版本。独立真实数据库再次暂停插入、跨发布恢复,得到 409 invalid_cursor。没有新增内容哈希或自制发布基线。
P2:迟到会话恢复已退出身份
位置:juku-mobile/src/auth/client.ts:108、:118。
修复前,先发起 SDK getSession 并延迟其带续期 Cookie 的响应,再执行退出。退出请求返回 503,原始只读对账确认服务端会话尚未撤销,此时本地 Cookie 已清空。放行旧 SDK 响应后,Expo 插件再次把旧用户 Cookie 写回 SecureStore。
现在使用框架的 disableRefresh 参数;退出取消旧请求并使旧客户端失效;SecureStore 写入按同一来源排队,拒绝旧客户端的迟到写入。Cookie 解析与登录协议仍由官方 SDK 负责。
使用真实 Better Auth 与 Expo 1.7.7 SDK,配合本地协议响应夹具独立复测:revoked=false,退出时和迟到响应后的 Cookie 均为空,旧会话返回 credentials_changed。这证明本地退出保持有效,并没有把服务端尚未撤销的会话说成已撤销。
可复用复现工具位于:/Users/alienmu/Documents/Codex/2026-10-02/bang/work/existing-project/consumer-auth-race-review.cjs,导出 runConsumerAuthRaceReview。
额外确认
- 真实管理员在数据库中降为运营后,原 JWT 的
/api/admins/me返回最新运营角色,发布立即返回 403。未发现角色撤销后仍能发布的问题。 - 消费者身份由 Better Auth 的有效、已验证邮箱会话产生;Go 没有把消费者身份提升为旧管理账号。查询服务不采用请求体中的伪造用户身份或
authenticated标志。 - 内部服务要求桥接凭据,Go 配置限制为回环地址;渠道权限由 Go 传入,查询会校验游标所属用户、查询条件及当前渠道集合。
- 后台发布入口使用 Payload 实际
req.user,Local API 读取配置时保留overrideAccess=false。消费者身份及只读运营角色不能发布。
验证范围
数据库复现使用独立 PostgreSQL 实例和官方迁移;后台权限复现经过 Payload 官方 REST 请求处理器,未依赖伪造的管理员对象。App 复现使用真实官方 SDK,但网络响应为本地协议夹具,没有替代真机、真实邮件投递或公网部署验收。
本轮没有测试邀请码奖励、播放额度、历史删除后的额度保持、完整离线下载或收费广告流程。它们仍按产品开发任务逐项实施和验收。
渠道重新归并时,如果旧统一剧集已经存在追剧或观看状态,当前实现返回 409 mapping_state_review_required,要求进入明确的状态迁移流程。现阶段不能宣称这些状态会自动迁移;本报告没有完成该后续迁移模块的验收。内容导入集数上限已与现有 Go 接口的 10000 保持一致。