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

7.4 KiB
Raw Permalink Blame History

编码规则(Coding Rules)

每次写代码前先读完本文件。这是让 AI 不跑偏、代码质量稳定的硬约束。 与技术细节冲突时,以 技术栈 / 架构设计 的事实为准;与“该不该做”冲突时,以 需求 为准。

0. 黄金法则

  1. 不臆造:数据字段、文件、接口、依赖、支付回调字段,不确定就查证或询问。
  2. 守范围:只做当前任务要求的事,不顺手加后续功能(如异步队列、报表、复杂活动赠点)。
  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 的功能。
  • V2 / V3 功能(异步队列、报表、复杂活动赠点 / 邀请奖励、自动退款对账)只记录,不实现。(自助注册/扫码充值/API Key 管理已纳入 MVP;新用户一次性注册送 10 点已由 T-608 落地。)
  • 需求明确排除的非目标不得实现(自建收银台、多币种、分账等)。
  • 不为“将来可能用到”提前抽象。

4. 架构纪律

  • 技术栈以 03-tech-stack.md 为准;新增依赖前先说明理由,未经确认不引入重量级依赖(Celery、Redis 等)。
  • 模块职责以 04-architecture.md 为准,不跨层偷写逻辑。
  • 点数余额只能经 apps/billing 修改:余额存 UserWallet(与 auth User 分离),扣点锁 wallet 行;API 层/Admin/用户端都不得直接写 points_balance。
  • 注册赠点也只能经 apps/billing 修改:当前 10 点试用额度必须走 grant_signup_bonus() 这类计费层服务,写 PointsLedger(signup_bonus),不得在 allauth adapter、view 或 signal 里直接把钱包余额设为 10。
  • API Key 哈希存储(sha256),明文只在生成时返回一次;不存明文、任何页面不回显。
  • 对外 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。
  • 对外接口只接受能力别名,不接受具体模型名;新增供应商必须走 apps/ai/providers/ 的适配器,不在 API 层写供应商分支逻辑。
  • 计费按别名定价,不按具体模型 SKU;不要把模型名写进对外契约或调用方文档。
  • 供应商 api_key 必须加密存储、使用时解密,不落明文、不在 admin 回显。
  • 内容安全顺序:若启用 prompt 敏感词过滤,必须在 image_url 下载 / image_base64 大图处理 / 别名解析 / 计费预扣之前审核 prompt;命中时返回 content_blocked,不扣点、不写 CallRecord / PointsLedger、不调上游。详细规则见 docs/moderation.md。
  • 接口形状以 api.md 为准,运营后台路由以 routes.md 为准。

5. 代码规范

  • 标识符使用英文;UI 文案、注释、文档使用中文,保持一致。
  • 错误必须处理,不吞错;上游/支付异常要分类并向上抛清晰错误。
  • 注释解释“为什么”,不复述“做了什么”。
  • 遵守项目格式化工具,不手工制造风格分裂。

6. 测试与验证

完成前至少检查:

  • 迁移成功(makemigrations + migrate 无误)。
  • 相关测试通过(python manage.py test)。
  • 对得上需求验收标准。
  • 没有夹带无关改动。
  • 涉及文档事实变化时,文档已同步。
  • 已在 ../progress.md 记录跑过的命令和结果作为证据,不靠“代码已写”判定完成。
  • 回复里如实说明跑了什么命令、结果如何。

真实命令:

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,运营手工调整必须填原因。
  • 注册赠点幂等:新用户 10 点试用额度必须有数据库级幂等保护,同一用户无论注册回调、重试或并发触发多少次,都最多发放一次;不得用 MySQL 不支持的条件唯一约束。
  • 敏感信息:密钥/凭证只用环境变量或后台配置,不写真实值进代码与文档。
  • 资金相关改动必须有对应测试(并发扣点、重复回调、上游失败退点至少各一条)。
  • 不绕过支付系统的鉴权、验签或风控。

9. 拿不准就问

问题要具体:说明卡在哪里、有哪些选项、倾向哪个选项及原因。尤其支付接口字段/签名、汇率与点数单价,缺信息时先问或先用标注清楚的 mock,不要凭空假设。