87 lines
6.7 KiB
Markdown
87 lines
6.7 KiB
Markdown
# Phase 0 骨架审核报告(T-001 ~ T-003)
|
||||
|
|
|
|||
|
|
> 审核人:Claude Code(全栈视角)|日期:2026-07-02|结论:**验收通过**。
|
|||
|
|
> 进入 Phase 1(T-101)前,建议先做 **T-004 骨架修补**(本文 P1/P2)。
|
|||
|
|
> 本文面向 codex 执行:每条修补项给出「症状 / 位置 / 怎么改 / 怎么验证」。修补任务见 [`06-tasks.md`](06-tasks.md) 的 **T-004**。
|
|||
|
|
|
|||
|
|
## 一、验收核对(全部达标)
|
|||
|
|
|
|||
|
|
| 任务 | 验收要点 | 结果 |
|
|||
|
|
| --- | --- | --- |
|
|||
|
|
| T-001 | manage.py 可跑、runserver 起得来、init 脚本真实命令、文档占位替换 | ✅ |
|
|||
|
|
| T-002 | 五个 app、**首迁移前定义自定义 User + `AUTH_USER_MODEL`**、env 读密钥无明文、MySQL+utf8mb4 | ✅ |
|
|||
|
|
| T-003 | superuser 能登录 `/admin/`、`manage.py test` 至少 1 条通过(实际 2 条) | ✅ |
|
|||
|
|
|
|||
|
|
## 二、做对的(勿在修补中回退)
|
|||
|
|
|
|||
|
|
以下是已正确落地的关键点,T-004 修补时**不要改坏**:
|
|||
|
|
|
|||
|
|
1. **自定义 User 先于首次迁移**:`apps/users/migrations/0001_initial.py` 只依赖 `auth`,`AUTH_USER_MODEL='users.User'` 已设,`db_table='user'`。Django 头号坑已避开。
|
|||
|
|
2. **PyMySQL 胶水**:`config/__init__.py` 的 `pymysql.install_as_MySQLdb()`——不可删。
|
|||
|
|
3. **密钥零泄露**:SECRET_KEY / DB 密码全走 env;`.env`、`ai_models.json` 均未被 git 跟踪且在 `.gitignore`。
|
|||
|
|
4. **测试库隔离**:坚持独立 `test_cmhub` 测试库,不碰业务库 `cmhub`。
|
|||
|
|
5. `cryptography` 依赖(MySQL8 `caching_sha2_password` + 未来 `api_key` 加密预留);admin 继承 `DjangoUserAdmin` 做脱敏/过滤/只读。
|
|||
|
|
|
|||
|
|
## 三、修补清单
|
|||
|
|
|
|||
|
|
### P1 · 现在改(趁地基未固化,低成本高收益)
|
|||
|
|
|
|||
|
|
#### P1-1 `User.email` 加 `unique=True`
|
|||
|
|
|
|||
|
|
- **症状**:`email` 必填但不唯一,允许同邮箱重复注册,与需求(`02-requirements.md`)「邮箱验证注册」语义冲突;后续 allauth 邮箱验证 / 找回密码通常要求 email 唯一。现在 `user` 表基本为空,是加约束的最便宜时机;拖到 T-501 再加要额外迁移 + 清洗重复数据。
|
|||
|
|
- **位置**:`apps/users/models.py`(`email` 字段定义处)。
|
|||
|
|
- **怎么改**:`email = models.EmailField("email address", unique=True)`。
|
|||
|
|
- **前提/权衡**:若产品最终确定「只用 username 登录、email 仅展示」,可不改——但需在本文此条标注「产品确认不需要」。**默认动作:加 unique。**
|
|||
|
|
- **注意**:改前确认业务库 `user` 表无重复邮箱(superuser 用唯一邮箱);否则先清理。
|
|||
|
|
- **验证**:`makemigrations users`(应生成一条 `AlterField`)→ `migrate` → `check` → `test` 全绿。
|
|||
|
|
|
|||
|
|
#### P1-2 `requires-python` 落地 + init 脚本校验解释器版本
|
|||
|
|
|
|||
|
|
- **症状**:`03-tech-stack.md` 要求「骨架须写死 `requires-python=">=3.12,<3.14"`,init 脚本校验解释器版本」。当前用 `requirements.txt`(表达不了 Python 版本约束),`init.sh`/`init.ps1` 只硬调 `python3.12` / `py -3.12` 命令、**无显式版本断言**——换台机器解释器指向 3.13 或不存在时不会明确报错。文档一致性欠账。
|
|||
|
|
- **位置**:项目根(无 `pyproject.toml`);`init.sh` 顶部;`init.ps1` 顶部。
|
|||
|
|
- **怎么改(二选一,取轻——推荐 A)**:
|
|||
|
|
- **A(推荐,最小改动)**:在 `init.sh` / `init.ps1` 安装依赖前加一步 Python 版本断言:解析解释器版本,若不在 `>=3.12,<3.14` 则打印错误并退出(非 0)。
|
|||
|
|
- **B**:新增 `pyproject.toml` 写 `requires-python=">=3.12,<3.14"`(仅在配合构建/安装工具时才强制,较重;若采用需同步 `03-tech-stack.md` 的依赖管理说明)。
|
|||
|
|
- **验证**:用非 3.12 解释器(或模拟)跑 init,应明确报错退出;用 3.12 正常走完安装 + `check`。
|
|||
|
|
|
|||
|
|
### P2 · 规范性(趁早理顺)
|
|||
|
|
|
|||
|
|
#### P2-1 `INSTALLED_APPS` 顺序
|
|||
|
|
|
|||
|
|
- **症状**:`rest_framework` 与 `apps.*` 排在整个 `django.contrib.*` **之前**。`APP_DIRS=True` 下模板按 `INSTALLED_APPS` 顺序查找——将来 `portal` 做用户端模板时,本地 app 模板会**优先于 admin**,若不慎放了同名模板(如 `admin/base_site.html`)会意外覆盖后台。当前无模板,是潜在隐患。
|
|||
|
|
- **位置**:`config/settings.py` 的 `INSTALLED_APPS`。
|
|||
|
|
- **怎么改**:调整为 `django.contrib.*`(admin/auth/contenttypes/sessions/messages/staticfiles)在前 → `rest_framework` → `apps.users|portal|billing|ai|api`。
|
|||
|
|
- **验证**:`check` / `test` 仍全绿;`/admin/` 正常。
|
|||
|
|
|
|||
|
|
#### P2-2 补 `.env.example`
|
|||
|
|
|
|||
|
|
- **症状**:`.gitignore` 有 `!.env.example` 白名单,说明本应提供样例,但文件缺失;新人不知道要配哪些环境变量。
|
|||
|
|
- **位置**:项目根。
|
|||
|
|
- **怎么改**:新增 `.env.example`,列出 `MYSQL_HOST/PORT/DATABASE/USER/PASSWORD/CHARSET`、`DJANGO_SECRET_KEY`、`DJANGO_DEBUG`、`DJANGO_ALLOWED_HOSTS` 等键,值用占位符(**不含任何真实值**)。以 `env.md` 为准。
|
|||
|
|
- **验证**:`git status` 显示 `.env.example` 被跟踪(未被 `.gitignore` 忽略)。
|
|||
|
|
|
|||
|
|
#### P2-3 同步根 `README.md` 当前状态
|
|||
|
|
|
|||
|
|
- **症状**:根 `README.md` 的「当前状态」仍停在 T-001 / 下一步 T-002,已落后于 T-003 完成后的现实状态。
|
|||
|
|
- **位置**:项目根 `README.md`。
|
|||
|
|
- **怎么改**:更新为 Phase 0 已完成、当前先做 T-004 修补、之后进入 T-101。
|
|||
|
|
- **验证**:`README.md` 与 `docs/current-state.md` 的下一步口径一致。
|
|||
|
|
|
|||
|
|
### P3 · 后续任务处理(**不在 T-004 范围**,仅登记)
|
|||
|
|
|
|||
|
|
- **REST_FRAMEWORK 认证配置**:`DEFAULT_AUTHENTICATION_CLASSES` 等(对外 API 只认 Key 不认 session)——留给 **T-301**。
|
|||
|
|
- **`sql_mode` 完整性**:`init_command` 仅 `STRICT_TRANS_TABLES`,会覆盖 MySQL 默认 sql_mode 其余项;对 InnoDB 防截断已够,可后续补 `NO_ENGINE_SUBSTITUTION` 等。
|
|||
|
|
- **生产 SECRET_KEY 保护**:`DEBUG=False` 且 `SECRET_KEY` 仍为默认 `django-insecure-*` 时应主动报错——留给部署任务 **T-403**。
|
|||
|
|
|
|||
|
|
## 四、说明:未本地复跑
|
|||
|
|
|
|||
|
|
审核机(WSL)无 `python3.12`,**未本地复跑 `check`/`test`**。本报告基于:静态审查(代码 + 迁移文件 + 配置)+ codex 的执行记录(记录含真实报错与修复过程:MySQL 授权、MySQL8 `caching_sha2_password` 需 `cryptography`,可信度高)。
|
|||
|
|
|
|||
|
|
T-004 修补后,请重跑 `check` / `test` / `init`,并把命令与结果记入 `progress.md` 作为证据(按 `06-tasks.md` 使用规则第 5 条)。
|
|||
|
|
|
|||
|
|
## 五、T-004 完成定义
|
|||
|
|
|
|||
|
|
- P1-1、P1-2、P2-1、P2-2、P2-3 全部处理(P1-1 若产品确认不需要则标注跳过)。
|
|||
|
|
- `check` 0 issues、`test` 全绿、`init` 通过,证据入 `progress.md`。
|
|||
|
|
- P3 各项已在 `06-tasks.md` 对应任务(T-301 / T-403)或 Backlog 有登记,不遗失。
|