核验为逐条实跑,不采信文档声称。阶段 0/1/2 出口标准全部通过, 其中阶段 2 判题链路端到端实测(注册→登录→提交→JudgeServer→WS 推送)。 覆盖率对账:oj 侧 65 条已全部实现,admin 侧 45 条一条未做。 新旧路径不同名(API 已重新设计),对照关系为人工按语义逐条比对。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4.2 KiB
4.2 KiB
阶段 0 / 1 / 2 出口标准核验
日期:2026-08-07 方法:逐条实跑,不采信文档声称。阶段 1 后半段至阶段 3 的实现由外部 agent(Codex)完成, 本次核验按外部代码对待,独立验证。
结论
| 阶段 | 出口标准条数 | 通过 | 结果 |
|---|---|---|---|
| 0 存量盘点 | 4 | 4 | ✅ |
| 1 骨架 | 5 | 5 | ✅ |
| 2 判题竖线 | 1(端到端) | 1 | ✅ |
阶段 0
| 标准 | 实测 |
|---|---|
endpoint-inventory.md 的 REVIEW 计数为 0 |
`grep -c '^ |
| 清单顶部记录最终数字 | 「合计 127 —— KEEP 110、CUT 17、REVIEW 0;新后端需实现 110 个」 |
| jieba 结论写回设计文档 7.3 | @node-rs/jieba 在文档中出现 6 处,7.3 节为实测结论 |
schema.sql 入库 |
git ls-files 命中 |
阶段 1
| 标准 | 实测 |
|---|---|
@oj2/contract 为符号链接 |
contract -> ../../packages/contract(另有 api、web 两个 workspace 链接) |
schema.ts 27 张表且无框架表 |
grep -c 'pgTable(' → 27;django_* / auth_* 匹配为空 |
/api/problems 返回真实数据 |
HTTP 200,返回中文标题含 emoji(如「🎮好耶!是大冒险!」),字段完整 |
apps/web 构建成功 |
bun run build 退出码 0 |
/dev-problems 显示 20 道题 |
GET /api/dev/problems → 200,题目数 20 |
旧 Chrome 兼容约束(硬约束)专项核验
学校机房浏览器版本低,mermaid-legacy 等 fallback 依赖与 legacy() 插件不可动。实测:
apps/web/vite.config.ts与ojnext/vite.config.ts差异 17 行,全部是新增代理 (/api2、/ws2、/public/avatar),未触碰legacy()插件与 Chrome 90 兼容配置- 依赖 38 → 39,新增仅
@oj2/contract,删除 0 个,mermaid-legacy仍在
约束守住。
阶段 2
出口标准:一名学生能登录、读公开题、提交代码,并通过 WebSocket 看到真实 JudgeServer 的判题结果。
实测流程(全部真实执行,非模拟):
- 注册
POST /api/users→ 201 - 登录
POST /api/auth/login→ 200,Set-Cookie: oj2_session=<32 字节随机令牌> - 会话
GET /api/me→ 200,返回用户身份 - 读公开题
GET /api/problems/1004→ 200 - 提交
POST /api/submissions→ 201,返回submissionId - 判题 真实 JudgeServer 执行,返回
result: 0(ACCEPTED),两个测试点均带memory/cpu_time/output_md5 - WebSocket 推送
ws://localhost:3000/ws/submissions,订阅后收到三条:
{"type":"submission_update","result":6,"status":"pending"}
{"type":"submission_update","result":7,"status":"judging"}
{"type":"submission_update","result":0,"status":"finished","time_cost":0,"memory_cost":1470464,"score":0}
- 统计回写 题目
myStatus变为 0(已通过)
附带核验:公开题详情无泄露
GET /api/problems/1004 的响应字段中不含 testCaseId、testCaseScore、answers、
astRules —— 学生侧看不到测试点与答案。
遗留待处理项(不影响上述判定)
GET /api/dev/problems与apps/web/src/oj/dev-problems.vue仍在。 二者是阶段 1 的 临时链路验证物,阶段 1 计划正文写明「阶段 3 会删」。apps/web/src/routes.ts里的dev-problems路由同样待删。- 占位用户
devadmin无法登录。 其password列是字面量'unusable'(非有效哈希),raw_password为'devonly'。这是阶段 1 为满足problem.created_by_id外键而造的占位记录, 设计如此,不是缺陷。需要管理员账号做本地验证时得另建。 - 判题容器健康状态依赖后端。
oj2-judge的 healthcheck 需要能连上后端心跳端点; API 未启动时docker compose ps会显示 unhealthy,属预期行为,非故障。
未覆盖
本次只核验出口标准,未做代码质量与安全审查。阶段 2、3 的实现均未经过任务级评审
(阶段 0、1 的评审曾逮到 _id/id 静默碰撞、端点漏抓 5 个、key() 误剥前缀等缺陷),
相关审查另行进行,见 phase3-review-authz.md 与 phase3-review-leakage.md。