Files
OJ2/docs/specs/phase012-verification.md
yuetsh 0f999aa5b1 docs: 阶段 0/1/2 出口标准核验 + 阶段 3 覆盖率对账
核验为逐条实跑,不采信文档声称。阶段 0/1/2 出口标准全部通过,
其中阶段 2 判题链路端到端实测(注册→登录→提交→JudgeServer→WS 推送)。

覆盖率对账:oj 侧 65 条已全部实现,admin 侧 45 条一条未做。
新旧路径不同名(API 已重新设计),对照关系为人工按语义逐条比对。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 01:25:36 -06:00

88 lines
4.2 KiB
Markdown
Raw 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.
# 阶段 0 / 1 / 2 出口标准核验
日期2026-08-07
方法:**逐条实跑,不采信文档声称**。阶段 1 后半段至阶段 3 的实现由外部 agentCodex完成
本次核验按外部代码对待,独立验证。
## 结论
| 阶段 | 出口标准条数 | 通过 | 结果 |
|---|---|---|---|
| 0 存量盘点 | 4 | 4 | ✅ |
| 1 骨架 | 5 | 5 | ✅ |
| 2 判题竖线 | 1端到端 | 1 | ✅ |
## 阶段 0
| 标准 | 实测 |
|---|---|
| `endpoint-inventory.md` 的 REVIEW 计数为 0 | `grep -c '^| REVIEW |'`**0** |
| 清单顶部记录最终数字 | 「合计 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 的判题结果。
实测流程(全部真实执行,非模拟):
1. **注册** `POST /api/users` → 201
2. **登录** `POST /api/auth/login` → 200`Set-Cookie: oj2_session=<32 字节随机令牌>`
3. **会话** `GET /api/me` → 200返回用户身份
4. **读公开题** `GET /api/problems/1004` → 200
5. **提交** `POST /api/submissions` → 201返回 `submissionId`
6. **判题** 真实 JudgeServer 执行,返回 `result: 0`ACCEPTED两个测试点均带
`memory` / `cpu_time` / `output_md5`
7. **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}
```
8. **统计回写** 题目 `myStatus` 变为 0已通过
### 附带核验:公开题详情无泄露
`GET /api/problems/1004` 的响应字段中**不含** `testCaseId``testCaseScore``answers`
`astRules` —— 学生侧看不到测试点与答案。
## 遗留待处理项(不影响上述判定)
1. **`GET /api/dev/problems``apps/web/src/oj/dev-problems.vue` 仍在。** 二者是阶段 1 的
临时链路验证物,阶段 1 计划正文写明「阶段 3 会删」。`apps/web/src/routes.ts` 里的
`dev-problems` 路由同样待删。
2. **占位用户 `devadmin` 无法登录。**`password` 列是字面量 `'unusable'`(非有效哈希),
`raw_password``'devonly'`。这是阶段 1 为满足 `problem.created_by_id` 外键而造的占位记录,
设计如此,不是缺陷。需要管理员账号做本地验证时得另建。
3. **判题容器健康状态依赖后端。** `oj2-judge` 的 healthcheck 需要能连上后端心跳端点;
API 未启动时 `docker compose ps` 会显示 unhealthy属预期行为非故障。
## 未覆盖
本次只核验出口标准,**未做代码质量与安全审查**。阶段 2、3 的实现均未经过任务级评审
(阶段 0、1 的评审曾逮到 `_id`/`id` 静默碰撞、端点漏抓 5 个、`key()` 误剥前缀等缺陷),
相关审查另行进行,见 `phase3-review-authz.md``phase3-review-leakage.md`