Files
cmhub/docs/05-coding-rules.md
T

102 lines
7.4 KiB
Markdown
Raw Normal View History

2026-07-01 17:42:10 +08:00
# 编码规则(Coding Rules)
> 每次写代码前先读完本文件。这是让 AI 不跑偏、代码质量稳定的硬约束。
> 与技术细节冲突时,以 [技术栈](03-tech-stack.md) / [架构设计](04-architecture.md) 的事实为准;与“该不该做”冲突时,以 [需求](02-requirements.md) 为准。
## 0. 黄金法则
1. **不臆造**:数据字段、文件、接口、依赖、支付回调字段,不确定就查证或询问。
2026-07-08 14:19:00 +08:00
2. **守范围**:只做当前任务要求的事,不顺手加后续功能(如异步队列、报表、复杂活动赠点)。
2026-07-01 17:42:10 +08:00
3. **照架构**:使用既定技术栈(Django+DRF+admin)和模块边界,不擅自引入新框架。
4. **小步改**:一次只解决一个问题,不夹带无关重构。
5. **可验证**:改完必须能迁移、能测试、对得上验收标准。
## 1. 动手前
- 按链路确认:`vision` → `requirements` → `tech-stack` → `architecture` → `api` → `tasks`。
- 找到本任务对应的验收标准,写之前就知道“怎么算做对”。
- 复用优先:AI 上游调用复用 `cmbot/src/services/ai_text_service.py`、`ai_image_service.py`,不另写一套。
- 如果需求含糊,或改动会偏离原则/架构,先问。
## 2. 事实来源纪律
- 只相信文档指定的权威源:本 `docs/`、`cmbot` 的 AI 服务代码与 `ai_models.json`、支付系统官方文档。
- 不从备份、草稿、旧导出文件里推断当前事实。
- 不虚构字段、接口、状态码、配置项、支付回调签名规则。
- 数据结构变化必须同步更新 `04-architecture.md`、`api.md` 和相关任务。
## 3. 范围纪律
- MVP 只做 `02-requirements.md` 中列为 P0 的功能。
2026-07-18 15:00:04 +08:00
- V2 / V3 功能(异步队列、报表、复杂活动赠点 / 邀请奖励、自动退款对账)只记录,不实现。(自助注册/扫码充值/API Key 管理已纳入 MVP;新用户一次性注册送 10 点已由 T-608 落地。)
2026-07-01 17:42:10 +08:00
- 需求明确排除的非目标不得实现(自建收银台、多币种、分账等)。
- 不为“将来可能用到”提前抽象。
## 4. 架构纪律
- 技术栈以 `03-tech-stack.md` 为准;新增依赖前先说明理由,未经确认不引入重量级依赖(Celery、Redis 等)。
- 模块职责以 `04-architecture.md` 为准,不跨层偷写逻辑。
- **点数余额只能经 `apps/billing` 修改**:余额存 `UserWallet`(与 auth `User` 分离),扣点锁 wallet 行;API 层/Admin/用户端都不得直接写 `points_balance`。
2026-07-18 15:00:04 +08:00
- **注册赠点也只能经 `apps/billing` 修改**:当前 10 点试用额度必须走 `grant_signup_bonus()` 这类计费层服务,写 `PointsLedger(signup_bonus)`,不得在 allauth adapter、view 或 signal 里直接把钱包余额设为 10。
2026-07-01 17:42:10 +08:00
- **API Key 哈希存储**(sha256),明文只在生成时返回一次;不存明文、任何页面不回显。
2026-07-06 10:44:13 +08:00
- **对外 API 只挂 API Key 认证,不挂 SessionAuthentication**;用户端页面用 session + CSRF;自助注册**免邮箱验证**(`ACCOUNT_EMAIL_VERIFICATION="none"`,邮箱仍必填且唯一)、生成接口须限流。
- **用户端与后台账号分离**:portal 与 `/admin/` 共用同一个 Django 会话(同一 `sessionid`),后台访问只多一道 `is_staff` 门槛。因此 **终端用户一律 `is_staff=False`**(普通用户登 portal 进不了后台,无泄露);**运营用专用 admin superuser 登录 `/admin/`,不要拿这个账号登 portal**——账号分离(方案 A)就是「解耦入口」的正解,不要为同账号双会话去拆 cookie/子域名。详见 `04-architecture.md`。
2026-07-01 17:42:10 +08:00
- **对外接口只接受能力别名,不接受具体模型名**;新增供应商必须走 `apps/ai/providers/` 的适配器,不在 API 层写供应商分支逻辑。
- 计费按别名定价,不按具体模型 SKU;不要把模型名写进对外契约或调用方文档。
- 供应商 `api_key` 必须加密存储、使用时解密,不落明文、不在 admin 回显。
2026-07-06 10:44:13 +08:00
- **内容安全顺序**:若启用 prompt 敏感词过滤,必须在 `image_url` 下载 / `image_base64` 大图处理 / 别名解析 / 计费预扣之前审核 prompt;命中时返回 `content_blocked`,不扣点、不写 `CallRecord` / `PointsLedger`、不调上游。详细规则见 `docs/moderation.md`。
2026-07-01 17:42:10 +08:00
- 接口形状以 `api.md` 为准,运营后台路由以 `routes.md` 为准。
## 5. 代码规范
- 标识符使用英文;UI 文案、注释、文档使用中文,保持一致。
- 错误必须处理,不吞错;上游/支付异常要分类并向上抛清晰错误。
- 注释解释“为什么”,不复述“做了什么”。
- 遵守项目格式化工具,不手工制造风格分裂。
## 6. 测试与验证
完成前至少检查:
- [ ] 迁移成功(`makemigrations` + `migrate` 无误)。
- [ ] 相关测试通过(`python manage.py test`)。
- [ ] 对得上需求验收标准。
- [ ] 没有夹带无关改动。
- [ ] 涉及文档事实变化时,文档已同步。
- [ ] 已在 `../progress.md` 记录跑过的命令和结果作为证据,不靠“代码已写”判定完成。
- [ ] 回复里如实说明跑了什么命令、结果如何。
真实命令:
```bash
python manage.py makemigrations && python manage.py migrate
python manage.py test
python manage.py runserver
```
## 7. 绝不
- 绝不把上游 api_key、支付密钥、SECRET_KEY、数据库密码等真实值写进代码或文档样例。
- 绝不为了让测试通过而删除断言、降低验收标准。
- 绝不擅自删除用户已有文件或重置工作区(尤其 `cmbot` 目录)。
- 绝不在没说明的情况下改公共接口、迁移数据结构或升级依赖。
## 8. 安全与合规(资金/点数专项,最高优先级)
涉及点数、金额、充值、扣费、退款时,必须全部满足:
- **并发安全扣点**:扣减点数必须用数据库事务 + `select_for_update()` 锁 `UserWallet` 行或 `F()` 原子更新,并配 DB 约束 `points_balance >= 0`(MySQL 的 CHECK 需 ≥8.0.16 才生效,不能只靠它),杜绝并发超扣或扣成负数。
- **充值幂等**:支付回调入账必须以 `order_no` 幂等,重复回调只入账一次。
- **回调验签**:支付回调必须验签,验签失败一律不入账并留痕;微信 V3 用 SDK 验签解密、支付宝用 SDK verify;缺商户密钥时按 mock 契约实现并标注待替换。
- **回调防护与兜底**:支付回调端点必须 `@csrf_exempt`(网关调用无 CSRF token);回调可能丢失,须提供按 `order_no` 主动查单兜底,避免已付款却一直 pending。
- **失败必退**:调用上游失败时,已预扣的点数必须冲正退回。
- **全程留痕**:每笔点数变动写 `points_ledger`,每次调用写 `call_record`,运营手工调整必须填原因。
2026-07-18 15:00:04 +08:00
- **注册赠点幂等**:新用户 10 点试用额度必须有数据库级幂等保护,同一用户无论注册回调、重试或并发触发多少次,都最多发放一次;不得用 MySQL 不支持的条件唯一约束。
2026-07-01 17:42:10 +08:00
- **敏感信息**:密钥/凭证只用环境变量或后台配置,不写真实值进代码与文档。
- 资金相关改动必须有对应测试(并发扣点、重复回调、上游失败退点至少各一条)。
- 不绕过支付系统的鉴权、验签或风控。
## 9. 拿不准就问
问题要具体:说明卡在哪里、有哪些选项、倾向哪个选项及原因。尤其支付接口字段/签名、汇率与点数单价,缺信息时先问或先用标注清楚的 mock,不要凭空假设。