53 KiB
当前实现状态
本文是可覆盖的当前快照,记录代码与任务看板的现实状态,帮助 AI coding agent 避免只看计划而忽略仓库现状。 历史执行流水追加到
../progress.md,不要在本文重复维护完整执行日志。
职责边界
06-tasks.md:任务看板,维护任务状态、依赖和验收要点。../progress.md:执行流水,只追加记录每轮执行、验证、阻塞和决策。current-state.md:当前快照,可覆盖更新当前目录、当前命令、已完成摘要和下一步。
当前快照
- 日期:2026-07-21
- 阶段:Phase 6 增强(MVP 后);Phase 3 对外 API 与充值已完成到 T-306,Phase 4 用户端 T-501 注册 / 登录(allauth)、T-502 API Key 自助管理页、T-503 个人中心 / 记录页、T-504 充值页与 T-505 用户端审核优化已完成,Phase 5 T-401 运营后台完善、T-402 MVP 完整验收与 T-403 部署 / 运行文档已完成,Phase 6 T-601 可用别名发现、T-602 django-admin 中文化第 1-3 层、T-603 django-admin 字段级中文化、T-604 中文敏感词本地过滤、T-605 免邮箱验证策略落地、T-606 公开首页 + 客户端下载入口、T-607 桌面端最新版本检查接口、T-608 新用户注册赠送试用点数(当前 10 点)、T-609 桌面端版本检查接口增加强制更新标记、T-610 首页导入模板下载入口、T-611 用户端品牌名统一为虾皮圈、T-612 生图同步接口止血、T-613 抽生成核心 service、T-614 生图异步任务化接口、T-615 旧同步生图接口遥测 / 弃用口径、T-616 生图失败自动重试 2 次、T-617 桌面端版本文件大小字段与 T-618 客户端发布版本后台必填校验元数据已完成;后续仍需处理真实支付回调到账闭环、客户端下载包发布和生产侧旧同步接口用量观察
- 技术栈:系统 Python 3.12.3 + Django 5.2.15 + DRF 3.16.1 + django-allauth 65.18.0 + PyMySQL 1.1.3 + cryptography 49.0.0 + requests 2.34.2 + ahocorapy 1.6.2 + wechatpayv3 2.0.2 + python-alipay-sdk 3.4.0 + django-admin;MySQL 8.4 已接入 settings,并支持
MYSQL_CONNECT_TIMEOUT/MYSQL_READ_TIMEOUT/MYSQL_WRITE_TIMEOUT;用户端已用 Django 模板 SSR + Bootstrap + allauth 落地注册登录;生产部署口径为 VPS / 宝塔 + Nginx + Gunicorn(gthread) + systemd;详见03-tech-stack.md与deployment.md - 生产代码:已有最小 Django 工程骨架:
manage.py、config/;T-002 已创建apps/users|portal|billing|ai|api;T-003 已把自定义User注册进 django-admin;T-004 已完成 email 唯一性、init 版本断言、app 顺序、.env.example与pyproject.toml;T-101 已新增apps/ai/providers/(Provider 接口、注册表、chat/gemini/images/images_edits 适配器);T-102 已新增AiModel/ModelAlias、Fernet 加密密钥存储、别名解析、admin 配置页、import_ai_models导入命令;T-103 已新增AiConfigAuditLog审计表、admin 只读页面和后台保存/删除审计 hook;T-104/T-105 已完成录制 title/image smoke 与审核修补;T-201 已新增UserWallet/ApiKey、PointsLedger/CallRecord、对应 admin 与迁移;T-202 已新增PricingRule/ExchangeRate、apps.billing.pricing计费计算函数、admin 配置页与迁移;T-203 已新增apps.billing.services,实现并发安全预扣、成功确认与幂等失败退点;T-204 已新增billing.0003_pointsledger_unique_ledger_change_type_per_call,用 MySQL 可落地的ref_call + change_type复合唯一约束兜底防重复 refund;T-301 已新增apps.api.authentication.ApiKeyAuthentication与ExternalApiView;T-302 已新增生成接口编排、序列化器、图片本地存储和/api/v1/generate/title|image路由;T-303 已新增apps.billing.services.get_balance_snapshot()与/api/v1/balance余额查询接口;T-304 已新增RechargeOrder、充值回调验签适配器、幂等入账服务、微信/支付宝回调路由与迁移billing.0004_rechargeorder_and_more;T-305 已新增create_recharge_order()、微信/支付宝扫码下单 mock/SDK 入口、/api/v1/recharge/create与/api/v1/recharge/status;T-306 已新增apps.api.throttles、apps.api.exceptions、REST_FRAMEWORK安全默认认证、生成/认证失败限流、image_urlSSRF 防护与响应大小上限、充值单笔金额上限;T-501/T-608 已接入 allauth 注册登录路径,注册成功后 adapter 调用grant_signup_bonus()经 billing 一次性发放 10 点并写signup_bonus流水,新增SignupBonusGrant(user UNIQUE)幂等标记、admin 只读检索和billing.0007迁移;T-502 已新增/apikeys、API Key 创建表单、列表页和删除(吊销)动作,生成后明文只显示一次,列表只显示 prefix;T-503/T-608 已扩展/dashboard为个人中心汇总,并新增/records/recharge充值记录与/records/usage点数记录,只读展示当前用户数据和注册赠点 / 消费 / 退款流水;T-504 已新增/recharge页面、RechargeCreateForm、充值导航入口和轮询脚本,页面创建 pending 订单、展示二维码票据、轮询/api/v1/recharge/status,订单 paid 后刷新余额;T-505 已把 Bootstrap 5 CSS 与 qrcode.js vendoring 到apps/portal/static/portal/vendor/,页面不再依赖 jsdelivr,并把充值记录 / 点数记录改为 DjangoPaginator分页;T-401 已新增adjust_wallet_points()手工调点服务、钱包 admin 专用调点表单与模板,后台可管理/检索用户、钱包、API Key(脱敏)、计费规则、汇率、充值订单、点数流水、注册赠点记录和调用记录,流水/订单/调用记录保持只读;T-402 已新增docs/mvp-acceptance.md,按 P0 验收矩阵记录 MVP 完整验收结论、测试证据和已知限制;T-403 已新增docs/deployment.md与requirements-production.txt,并在 settings 中补齐STATIC_ROOT、CSRF_TRUSTED_ORIGINS、共享CACHES、HTTPS cookie、proxy SSL、HSTS 环境变量与ACCOUNT_SIGNUP_RATE_LIMIT注册限流配置;T-601 已新增apps.ai.catalog.get_public_model_catalog()、GET /api/v1/models与 portal/models只读页面,只展示 active 可调用别名、能力、是否需要原图和点数单价,不解密 provider key,不暴露底层 SKU / URL / key /extra_body;T-604 已新增apps.moderation、SensitiveWord模型/admin/迁移、keyword provider、归一化管线和共享 cache 版本失效,生成接口已改为 prompt 先审再读取图片/计费/扣点/调上游;T-606 已新增公开首页/、DownloadRelease模型/admin/迁移、首页 SSR 模板、共享portal/brand.css,并把现有 portal 页面套入同一套品牌 token;T-607/T-609 已新增ClientLatestReleaseView与/api/v1/client/releases/latest,公开匿名返回当前客户端版本 JSON,release.force_update表示该版本是否强制升级;portal.0002_downloadrelease_force_update已给DownloadRelease增加force_update字段,admin 可编辑和筛选;T-610 已新增ImportTemplate模型/admin/迁移portal.0003_importtemplate,首页读取当前模板并在“下载客户端”旁展示“下载导入模板”,本地文件 URL 转为当前站点绝对 URL,external_url优先;T-611 已把用户端 portal 可见品牌名统一为“虾皮圈”,包括页面标题、顶部导航、首页 H1、用户端“虾皮圈 API Key”文案和 allauth 邮件模板;T-612 已新增AI_IMAGE_UPSTREAM_DEADLINE_SECONDS,生图 Provider 上游请求和上游返回图片 URL 下载会按min(AiModel.timeout_seconds 或分辨率默认值, 硬截止)控制读取超时,超时返回upstream_timeout并走既有失败退点路径;T-613 已把旧同步生成链路抽成GenerationInput、prepare_generation()、precharge_generation()、execute_precharged_generation()与GenerationResult,旧 view 只负责 serializer 和异常转 HTTP,后续异步 worker 可复用已预扣执行 / 确认 / 退点阶段。 - T-614/T-616 生产代码补充:已新增
ImageGenerationTask与api.0001_initial,新增POST /api/v1/generate/image/tasks、GET /api/v1/generate/image/tasks/{task_id}、apps.api.image_tasks任务服务、run_image_tasksmanagement command 和只读 admin;异步提交支持Idempotency-Key去重 / 冲突检测,worker 使用 DB 任务表、租约、心跳与 reaper,成功返回 cmhub 托管 URL;T-616 已通过api.0002_imagegenerationtask_next_attempt_at_and_more增加next_attempt_at与(status, next_attempt_at)索引,临时性upstream_timeout/upstream_error默认最多重试 2 次,重试期间不退点,最终失败 / 僵任务才走计费层幂等退款。 - T-617 生产代码补充:
DownloadRelease已新增size_bytes可空正整数字段和迁移portal.0004_downloadrelease_size_bytes,django-admin 可填写并在列表展示;GET /api/v1/client/releases/latest的release对象新增size_bytes,有值返回整数,未配置返回null,未发布时仍只返回release:null。 - T-618 生产代码补充:
DownloadReleaseAdmin已挂专用ModelForm,后台新增 / 编辑客户端发布版本时sha256与size_bytes必填;数据库字段仍兼容历史空值,API 仍可读取历史size_bytes=null记录。 - T-624~T-627 本地代码补充:
apps.licensing已包含设备、会话、设备审计、套餐、权益、席位、授权事件、存量迁移资格、迁移请求和设备凭证;licensing.0003_alter_licenseevent_action_legacymigrationgrant_and_more建立迁移数据与凭证 hash 存储。旧 API Key + 当前设备会话只能申请短时迁移,portal 同账号确认后才绑定席位;无会话旧客户端及现有生成/异步轮询保持不变,尚未部署生产。 - T-619 生产代码补充:
ModelAlias/CallRecord已新增vision操作并生成ai.0005/billing.0008迁移;POST /api/v1/analyze/images已接入 API Key 鉴权、生成限流、prompt 前置审核、有序多图 URL/Base64 读取、SSRF 与大小保护、Chat/Gemini 多模态 Provider、固定单次预扣 / 成功确认 / 幂等退款及安全调用摘要。模型目录与 portal 可用模型页会展示能力匹配的 activevision别名并标记requires_image=true。2026-07-16 已在185.216.248.75部署707941a并应用迁移,复用 activeGPT-5.5 文本(text + vision)创建默认 activevision-standard,默认价格为 1 点/次;Nginx 已把该同步接口分流到cmhub-generate长请求池。 - T-619 生产验收:真实提交两张图片成功返回中文文字,HTTP 200,
model_used=gpt-5.5,call_id=6096;余额 234→233,调用记录为vision/success,对应 consume 1 条、refund 0 条。验收临时 API Key 已吊销;cmhub-web、cmhub-generate、Nginx、MySQL 8.4 均为 active,66 个异步生图 worker 未因本次部署重启。 - 最新验证:T-619 已完成
ai.0005_alter_modelalias_operation_type与billing.0008_alter_callrecord_operation_type_and_more迁移并应用到当前开发库;manage.py check0 issues,makemigrations --check --dry-run无变化;Provider 专项 10 tests OK,T-619 API / 别名 / 目录专项 13 tests OK,包含旧标题 / 生图的扩展回归 84 tests OK,users / billing / moderation 分组 46 tests OK。完整单命令回归在 604 秒达到执行器超时,之后 API 全量重试在测试库初始化阶段遇到远程 MySQL43.128.3.240连接超时,均未产生断言失败;测试期仍有 allauth 在 MySQL 条件唯一约束上的既有models.W036警告。 - 验证补充:API 全量 88 条测试已重试两次,均在执行断言前因远程 MySQL 握手超时中断;
Test-NetConnection 43.128.3.240 -Port 3306同期显示 TCP 可达。收尾./init.ps1通过(Python 3.12.3,Django system check 0 issues)。 - 验证恢复:远程 MySQL 恢复后,新增“单图 + 指定 vision 别名”成功测试 1 test OK;API 非生成类拆分为鉴权 / 余额 / 模型目录 / 客户端版本 28 tests OK、充值回调 / 下单状态 13 tests OK,结合此前
GenerateApiTests整类回归与新增单测,当前 API 89 条均有通过证据;apps.portal.tests全量 39 tests OK。因此完整回归已通过拆分执行完成,单命令超时仅作为环境现象保留。 - 最新验证:T-618 客户端发布版本后台必填文件校验元数据已验证
.\init.ps1开工前通过;py -3.12 manage.py check通过,0 issues;py -3.12 manage.py makemigrations --check --dry-run通过,No changes detected;py -3.12 manage.py test apps.portal.tests.PortalAccountFlowTests.test_download_release_admin_requires_sha256_and_size_bytes apps.portal.tests.PortalAccountFlowTests.test_download_release_admin_saves_valid_release_metadata apps.api.tests.ClientLatestReleaseApiTests.test_latest_release_returns_null_size_bytes_when_not_configured apps.api.tests.ClientLatestReleaseApiTests.test_latest_release_is_public_without_api_key_and_returns_current_release --keepdb --noinput --verbosity 2通过,4 tests OK。测试期仍保留 allauth 在 MySQL 条件唯一约束上的既有models.W036警告。 - 最新验证:T-617 桌面端版本文件大小字段已验证
py -3.12 manage.py makemigrations --check --dry-run通过,No changes detected;py -3.12 manage.py check通过,0 issues;py -3.12 manage.py test apps.api.tests.ClientLatestReleaseApiTests --keepdb --noinput --verbosity 2通过,12 tests OK,覆盖size_bytes有值、未配置为null、未发布不返回顶层字段、响应字段白名单和 admin 字段可见;py -3.12 manage.py migrate portal --noinput120 秒超时,但py -3.12 manage.py showmigrations portal确认portal.0004_downloadrelease_size_bytes已应用,且无残留 migrate 进程。测试期仍保留 allauth 在 MySQL 条件唯一约束上的既有models.W036警告。 - T-614 实现取舍补充:worker 执行前会基于任务快照复跑
prepare_generation(),即复审 prompt 并重解析别名 / Provider / 定价;账务使用已预扣CallRecord.points_cost,不会重复扣点。短队列下这是偏安全取舍,词库变更后排队任务仍可被拦截并退款;若后续队列积压或频繁切换模型,应单独做提交时模型配置快照。异步 submit 对image_base64只解码并保存输入文件,桌面端主链路推荐继续使用;image_url会在 submit 阶段完成 SSRF 校验、远程下载和大小限制,可能阻塞提交请求,属于边缘兼容路径。 - T-615 生产代码补充:已新增
apps.api.telemetry,旧同步POST /api/v1/generate/image与新异步提交POST /api/v1/generate/image/tasks都写cmhub.api.generation_usage结构化日志事件generation_route_usage;字段白名单为route_type、API Key ID/前缀、user_id、X-Client-Version、别名、状态、耗时、错误码和 HTTP 状态,不记录 API Key 明文、prompt、图片 base64 或 provider raw。 - 异步生图 worker 排障补充:
run_image_tasks每处理一个任务会输出event=image_task_processed task_id=... status=... alias=... attempt=... max_attempts=... retrying=... next_attempt_at=... duration_ms=...,重试中 / 失败 / 过期任务额外输出error_code;日志不包含 prompt、image_base64、provider raw 或密钥。生产扩容 worker 应按 2、4、8、16 逐级观察队列长度、耗时、错误码、MySQL 连接数和上游失败率,不建议直接扩到 100。 - 最新验证:T-616 生图失败自动重试 2 次已验证
py -3.12 -m py_compile apps\api\generation.py apps\api\image_tasks.py apps\api\management\commands\run_image_tasks.py apps\api\models.py apps\api\admin.py apps\api\tests.py config\settings.py通过;py -3.12 manage.py makemigrations api生成api.0002_imagegenerationtask_next_attempt_at_and_more;py -3.12 manage.py migrate api --noinput已把api.0001/api.0002应用到当前开发库;py -3.12 manage.py check通过,0 issues;py -3.12 manage.py makemigrations --check --dry-run通过,No changes detected;T-616 新增 5 条目标测试通过,覆盖首次超时回队列不退点、两次超时后三次成功只扣一次、连续三次超时最终只退一次、非重试错误立即退款、worker 重试日志字段和敏感信息不泄露;异步生图旧行为回归 12 tests OK;py -3.12 manage.py test apps.api.tests.GenerateApiTests --keepdb --noinput --verbosity 2通过,37 tests OK;.\init.ps1通过;git diff --check通过,仅 Windows CRLF 提示。测试期仍保留 allauth 在 MySQL 条件唯一约束上的既有models.W036警告。 - 最新验证:T-615 旧同步生图接口遥测已验证
py -3.12 -m py_compile apps\api\telemetry.py apps\api\views.py apps\api\tests.py通过;新增 3 条目标测试通过,覆盖旧同步成功日志、新异步提交成功日志、异步余额不足错误日志,确认可按 client version / api_key / route_type 查询且不泄露 prompt、base64、完整 API Key 或 provider raw;py -3.12 manage.py check通过,0 issues;py -3.12 manage.py makemigrations --check --dry-run通过,No changes detected;py -3.12 manage.py test apps.api.tests.GenerateApiTests --keepdb --noinput --verbosity 2通过,31 tests OK;.\init.ps1通过;git diff --check通过,仅 Windows CRLF 提示。测试期仍保留 allauth 在 MySQL 条件唯一约束上的既有models.W036警告。 - 用户端导航:顶部导航 active 状态已修复,
portal/base.html基于request.resolver_match.url_name高亮当前页面入口,并用aria-current="page"标记;「充值」不再在非充值页固定深色高亮。 - 最新验证:T-614 生图异步任务化接口已验证
py -3.12 manage.py makemigrations api生成api.0001_initial;py -3.12 manage.py test apps.api.tests.GenerateApiTests -v 2 --keepdb通过,28 tests OK,覆盖敏感词拦截不建任务/不扣点、余额不足 402、Idempotency-Key 去重和冲突、worker 成功轮询同一 URL、跨用户拒绝、失败/超时退款、reaper 僵任务退款、重复 worker 幂等和 reaper 退款后的迟到 worker 不可改回成功。首次不带--keepdb运行时因已有test_cmhub触发交互式删除确认导致 EOF 中断;重跑--keepdb通过。测试期仍保留 allauth 在 MySQL 条件唯一约束上的既有models.W036警告。 - 最新验证:T-613 抽生成核心 service 已验证
.\init.ps1开工前通过;py -3.12 -m py_compile apps\api\generation.py apps\api\storage.py apps\api\views.py apps\api\tests.py通过;py -3.12 manage.py check通过,0 issues;py -3.12 manage.py makemigrations --check --dry-run通过,No changes detected;T-613 新增核心 service 目标测试 2 tests OK;py -3.12 manage.py test apps.api.tests.GenerateApiTests --keepdb --noinput --verbosity 1通过,19 tests OK;.\init.ps1收尾通过;git diff --check通过,仅 Windows CRLF 提示。曾尝试py -3.12 manage.py test apps.api --keepdb --noinput --verbosity 1,命令 484 秒超时无断言结果;拆跑非生成 API 测试类时在测试库 setup 阶段出现远程 MySQL43.128.3.240连接超时OperationalError(2003),期间Test-NetConnection 43.128.3.240 -Port 3306显示端口可达。测试期仍保留 allauth 在 MySQL 条件唯一约束上的既有models.W036警告。 - 最新验证:T-612 生图同步接口止血已验证
py -3.12 -m py_compile config\settings.py apps\ai\providers\utils.py apps\ai\providers\openai_compatible.py apps\api\generation.py apps\ai\tests.py apps\api\tests.py通过;py -3.12 manage.py check通过,0 issues;py -3.12 manage.py makemigrations --check --dry-run通过,No changes detected;生图 Provider 目标测试 3 tests OK,确认生图上游请求与返回图片 URL 下载会被AI_IMAGE_UPSTREAM_DEADLINE_SECONDS截断,文本生成不受该硬截止影响;GenerateApiTests.test_image_upstream_timeout_refunds_precharged_points_and_marks_call_failed通过;GenerateApiTests整组 17 tests OK;.\init.ps1收尾通过;git diff --check通过,仅 Windows CRLF 提示。测试期仍保留 allauth 在 MySQL 条件唯一约束上的既有models.W036警告。 - 最新验证:T-611 用户端品牌名统一为虾皮圈已验证
py -3.12 manage.py check通过,0 issues;py -3.12 manage.py makemigrations --check --dry-run通过,No changes detected;git diff --check通过,仅 Windows CRLF 提示;py -3.12 manage.py test apps.portal.tests.PortalAccountFlowTests.test_homepage_is_public_and_shows_anonymous_onboarding_without_release apps.portal.tests.PortalAccountFlowTests.test_homepage_shows_current_download_release apps.portal.tests.PortalAccountFlowTests.test_portal_pages_use_shopee_circle_branding --keepdb --noinput --verbosity 2通过,3 tests OK。测试期仍保留 allauth 在 MySQL 条件唯一约束上的既有models.W036警告。 - 测试:T-601 已验证:
.\init.ps1通过(Python 3.12.3,依赖已满足,manage.py check0 issues,打印启动命令);py -3.12 -m py_compile apps\ai\catalog.py apps\api\views.py apps\api\urls.py apps\api\tests.py apps\portal\views.py apps\portal\urls.py apps\portal\tests.py通过;py -3.12 manage.py check通过;py -3.12 manage.py makemigrations --check --dry-run无变化;git diff --check通过;py -3.12 manage.py test apps.api.tests.ModelsCatalogApiTests apps.portal.tests.PortalAccountFlowTests.test_models_page_requires_session_login apps.portal.tests.PortalAccountFlowTests.test_models_page_lists_public_aliases_prices_and_unpriced_state --keepdb --noinput --verbosity 2首次运行时 3 条 API 测试已通过,portalsetUpClass阶段因远程 MySQL 连接 43.128.3.240 超时中断;随后Test-NetConnection 43.128.3.240 -Port 3306显示TcpTestSucceeded=True,单独重跑两条 portal 测试通过,2 tests OK。T-403 已验证:./init.ps1开工前通过;py -3.12 manage.py check通过;py -3.12 manage.py makemigrations --check --dry-run无变化;py -3.12 manage.py findstatic portal/vendor/bootstrap/bootstrap.min.css portal/vendor/qrcode/qrcode.js --verbosity 1找到两个本地 static 文件;py -3.12 manage.py check --deploy在当前开发.env下仅报预期安全配置警告,临时注入生产型安全环境变量(含 HSTS includeSubDomains/preload)后通过,0 issues;py -3.12 manage.py collectstatic --dry-run --noinput通过,预期收集 169 个 static 文件;py -3.12 manage.py createcachetable --dry-run cmhub_cache通过,输出 MySQL cache 表 DDL;py -3.12 -m compileall config通过;尝试py -3.12 manage.py test apps.api --noinput --keepdb --verbosity 2时 25 条用例已通过,GenerateApiTests14 条因远程 MySQL 连接重置/事务中断被记 ERROR,随后Test-NetConnection 43.128.3.240 -Port 3306端口可达,单独重跑py -3.12 manage.py test apps.api.tests.GenerateApiTests --noinput --keepdb --verbosity 2通过,14 tests OK。测试/迁移阶段仍有 allauthaccount.EmailAddress条件唯一约束在 MySQL 上不可创建的models.W036警告;本项目用户账本邮箱唯一性由user.email唯一约束承担。 - 最新验证:T-608 新用户注册赠送试用点数(当前 10 点)已验证
py -3.12 -m py_compile config\settings.py apps\billing\models.py apps\billing\services.py apps\billing\admin.py apps\portal\adapters.py apps\portal\views.py apps\billing\tests.py apps\portal\tests.py通过;py -3.12 manage.py check通过,0 issues;py -3.12 manage.py makemigrations --check --dry-run通过,No changes detected;py -3.12 manage.py migrate billing --noinput通过,No migrations to apply;注册赠点服务和并发幂等目标测试 3 tests OK;注册限流配置测试 1 test OK;portal 注册赠点、首页文案、导航、dashboard 和点数记录目标测试 6 tests OK;SignupBonusGrantadmin 注册 smoke 1 test OK;.\init.ps1收尾通过(Python 3.12.3,依赖已满足,manage.py check0 issues,打印启动命令);git diff --check通过,仅 Windows CRLF 提示。测试期仍有 allauth 在 MySQL 条件唯一约束上的既有models.W036警告;一次 portal 目标测试启动阶段曾因远程 MySQL 连接43.128.3.240超时中断,端口探测恢复后重跑通过。 - 最新验证:T-607 桌面端最新版本检查接口已验证
.\init.ps1开工前通过;py -3.12 -m py_compile apps\api\views.py apps\api\urls.py apps\api\tests.py通过;py -3.12 manage.py check通过,0 issues;py -3.12 manage.py makemigrations --check --dry-run通过,No changes detected;py -3.12 manage.py test apps.api.tests.ClientLatestReleaseApiTests --keepdb --noinput --verbosity 2通过,9 tests OK;py -3.12 manage.py test apps.api.tests.ApiKeyAuthenticationTests apps.api.tests.BalanceApiTests apps.api.tests.ModelsCatalogApiTests apps.api.tests.ClientLatestReleaseApiTests --keepdb --noinput --verbosity 2通过,25 tests OK;py -3.12 manage.py test apps.api --keepdb --noinput --verbosity 1通过,54 tests OK;.\init.ps1收尾通过;git diff --check通过,仅 Windows CRLF 提示。测试期仅保留 allauth 在 MySQL 条件唯一约束上的既有models.W036警告。 - 最新验证:T-606 公开首页 + 客户端下载入口已验证
.\init.ps1通过(Python 3.12.3,依赖已满足,manage.py check0 issues,打印启动命令);py -3.12 -m py_compile apps\portal\models.py apps\portal\admin.py apps\portal\views.py apps\portal\urls.py apps\portal\tests.py通过;py -3.12 manage.py check通过,0 issues;py -3.12 manage.py makemigrations --check --dry-run通过,No changes detected;py -3.12 manage.py migrate portal已应用portal.0001_initial到当前数据库;py -3.12 manage.py shell -c "... Client().get('/') ..."返回STATUS=200、首页标识和下载区标识均存在;py -3.12 manage.py findstatic portal/brand.css portal/vendor/bootstrap/bootstrap.min.css portal/vendor/qrcode/qrcode.js --verbosity 1均找到;py -3.12 manage.py test apps.portal.tests.PortalAccountFlowTests.test_homepage_is_public_and_shows_anonymous_onboarding_without_release apps.portal.tests.PortalAccountFlowTests.test_homepage_shows_current_download_release apps.portal.tests.PortalAccountFlowTests.test_homepage_shows_dashboard_entry_for_authenticated_user apps.portal.tests.PortalAccountFlowTests.test_download_release_only_keeps_one_current_per_platform apps.portal.tests.PortalAccountFlowTests.test_authenticated_nav_highlights_current_page_only --noinput --verbosity 2通过,5 tests OK。py -3.12 manage.py test apps.portal.tests.PortalAccountFlowTests --keepdb --noinput --verbosity 2已重跑,因远程 MySQL43.128.3.240在测试库迁移阶段连接超时(2003 / WinError 10060)中断,不是断言失败;数据库恢复后需补跑 portal 整组。 - 最新验证:T-605 免邮箱验证策略已验证
py -3.12 -m py_compile config\settings.py apps\portal\tests.py通过;py -3.12 manage.py check通过,0 issues;py -3.12 manage.py makemigrations --check --dry-run通过,No changes detected;更新后的注册 / 登录目标测试 3 tests OK;py -3.12 manage.py test apps.portal --keepdb --noinput --verbosity 2通过,26 tests OK;git diff --check通过,仅 Windows CRLF 提示。全量py -3.12 manage.py test --keepdb --noinput --verbosity 2已尝试,发现 131 tests,跑到 95 tests 后远程 MySQL43.128.3.240出现连接超时 / WinError 10051,最终 22 errors;随后Test-NetConnection 43.128.3.240 -Port 3306显示TcpTestSucceeded=True,单独复跑失败起点的 billing 分组时 17 条业务用例 OK,并发扣点用例本体打印ok后在测试库 flush 阶段再次因 MySQL 连接超时 / WinError 10060 记 ERROR。结论:T-605 相关测试已通过,全量单次绿受远程 MySQL 稳定性阻塞。 - 最新验证:T-604 中文敏感词本地过滤已验证
py -3.12 -m py_compile config\settings.py apps\api\generation.py apps\api\tests.py apps\moderation\apps.py apps\moderation\models.py apps\moderation\normalization.py apps\moderation\policy.py apps\moderation\services.py apps\moderation\signals.py apps\moderation\versioning.py apps\moderation\providers\base.py apps\moderation\providers\keyword.py apps\moderation\tests.py通过;py -3.12 manage.py check通过,0 issues;py -3.12 manage.py makemigrations --check --dry-run通过,No changes detected;py -3.12 manage.py test apps.moderation --keepdb --noinput --verbosity 2通过,7 tests OK;新增生成接口目标测试 2 tests OK;py -3.12 manage.py test apps.api.tests.GenerateApiTests --keepdb --noinput --verbosity 2通过,16 tests OK。测试期仅保留 allauth 在 MySQL 条件唯一约束上的既有models.W036警告。 - 最新验证:T-603 django-admin 字段级中文化已收尾:人工确认
/admin/字段标签中文化;py -3.12 manage.py check通过,0 issues;py -3.12 manage.py makemigrations --check --dry-run通过,No changes detected;py -3.12 manage.py test apps.users.tests apps.billing.tests.BillingAdminTests apps.ai.tests.AiModelAdminTests apps.ai.tests.AiConfigAuditAdminTests --keepdb --noinput --verbosity 2通过,15 tests OK。测试期仅保留 allauth 在 MySQL 条件唯一约束上的既有models.W036警告。 - 线上 AI 标题生成缺陷已修复:2026-07-06 用当前线上
AI_KEY_ENCRYPTION_KEY重新导入/secure/cmhub/ai_models.json,修复title-standard对应AiModel.api_key_encrypted无法解密的问题。验证:python3.12 manage.py check通过;python3.12 manage.py smoke_ai_generation title真实调用成功,model_used=gpt-5.5,耗时约 16.9s,返回 3 个标题;用api_key.txt第二个 Key 调POST https://cm.833729.com/api/v1/generate/title成功返回 5 个标题,points_cost=1,余额从 1010 扣到 1009。 - 线上热修验证:
/admin/billing/exchangerate/500 根因是ExchangeRateAdmin.date_hierarchy触发 MySQLCONVERT_TZ,而生产 MySQL 未加载时区表,Django 抛ValueError: Database returned an invalid datetime value;已移除apps.billing.admin中 4 个 DateTimedate_hierarchy,保留list_filter日期筛选。验证py -3.12 -m py_compile apps\billing\admin.py apps\billing\tests.py、py -3.12 manage.py check、py -3.12 manage.py test apps.billing.tests.BillingAdminTests.test_exchange_rate_changelist_renders_when_rates_exist --keepdb --noinput --verbosity 2均通过。 - Mock 支付提示:
PAYMENT_CALLBACK_MODE=mock时,用户端/recharge的待支付订单区域会显示醒目测试模式提示,说明二维码只用于联调订单创建、页面渲染和状态轮询,不能使用微信或支付宝真实付款;sdk模式不显示该提示。验证py -3.12 -m py_compile apps\portal\views.py apps\portal\tests.py、py -3.12 manage.py check、py -3.12 manage.py test apps.portal.tests.PortalAccountFlowTests.test_recharge_page_post_creates_pending_order_without_crediting_wallet_or_ledger apps.portal.tests.PortalAccountFlowTests.test_recharge_page_does_not_show_mock_notice_in_sdk_mode --keepdb --noinput --verbosity 2均通过。 - 微信正式下单热修:线上微信 Native 下单失败根因是
wechatpayv3SDK 需要显式pay_type=WeChatPayType.NATIVE,且成功响应为(status_code, json_string)tuple 而非 dict;已兼容 tuple/json 响应并覆盖下单与主动查单。线上用修复后的_create_wechat_payment_order_with_sdk()创建 1 分诊断预支付请求,确认返回weixin://wxpay/bizpayurl票据。另:pending 订单主动查单异常不再让/api/v1/recharge/status返回 500,而是保持当前订单状态返回 200。 - 支付宝临时下线:线上支付宝预下单返回
isv.illegal-client-ip(当前调用 IP 不在支付宝可信名单中),需在支付宝开放平台把 VPS 出口 IP43.128.3.240加入可信 IP 后再恢复。因此用户端/recharge表单暂时只展示并接受微信支付;底层 API、模型枚举、回调与支付宝 SDK 路径保留不删。 - 数据:AI 上游调用与模型配置参考
D:\chengma\cmbot(src/services/ai_text_service.py、ai_image_service.py、config/ai_models.json);真实ai_models.json不提交,需通过import_ai_models命令加密导入 - 标准启动路径:Windows 用
./init.ps1;Unix/WSL 用./init.sh - 标准验证路径:Windows 用
py -3.12 manage.py check/py -3.12 manage.py test - 设计基线:自助用户端 + 对外 API + 运营后台三合一单体;用户模型
User(auth)/UserWallet(点数,锁 wallet 扣点)/ApiKey(1:N,哈希存储);生成标题、生成图片和多图理解均通过能力别名 + Provider 适配器对外提供,不暴露具体供应商模型;自助扫码充值;新用户注册成功一次性赠送 10 点试用点数,必须经 billing 写signup_bonus流水,且通过SignupBonusGrant(user UNIQUE)防重复发放。详见04-architecture.md与 2026-07-08 的progress.md决策 - 配置基线:运行环境变量集中见
docs/env.md;真实密钥/支付凭证不得写入代码或文档样例。用户端注册策略固定为ACCOUNT_EMAIL_VERIFICATION="none":免邮箱验证、注册即可用、邮箱仍必填且唯一;DJANGO_EMAIL_BACKEND/DJANGO_DEFAULT_FROM_EMAIL仅用于后续密码找回、通知或恢复邮箱验证等邮件能力,不作为当前注册登录前置条件。充值订单在创建时锁定汇率与预计点数,回调入账使用订单值,不按新汇率重算。支付回调与下单由PAYMENT_CALLBACK_MODE控制:本地/测试可用 HMACmock,生产应为sdk;二维码本地有效期提示由PAYMENT_QR_EXPIRES_MINUTES控制。T-306 起对外 API 安全配置包含API_GENERATE_THROTTLE_RATE、API_AUTH_FAILURE_THROTTLE_RATE、IMAGE_URL_MAX_BYTES、IMAGE_URL_MAX_REDIRECTS、IMAGE_URL_CONNECT_TIMEOUT_SECONDS、IMAGE_URL_READ_TIMEOUT_SECONDS、RECHARGE_MAX_AMOUNT_CNY。T-403 起生产静态、共享 cache 与 HTTPS 安全配置包含STATIC_URL、STATIC_ROOT、DJANGO_CACHE_BACKEND、DJANGO_CACHE_LOCATION、DJANGO_CSRF_TRUSTED_ORIGINS、DJANGO_SESSION_COOKIE_SECURE、DJANGO_CSRF_COOKIE_SECURE、DJANGO_SECURE_SSL_REDIRECT、DJANGO_SECURE_PROXY_SSL_HEADER、DJANGO_SECURE_HSTS_SECONDS。T-604 起内容安全配置包含MODERATION_ENABLED、MODERATION_PROVIDER=keyword、MODERATION_FAIL_CLOSED、MODERATION_BLOCK_ON_REVIEW、MODERATION_CACHE_VERSION_KEY;生产多 worker 下必须使用共享 cache 承载敏感词版本号。T-612 起生图同步接口止血配置包含AI_IMAGE_UPSTREAM_DEADLINE_SECONDS,只作用于generate_image上游读取硬截止。T-614/T-616 起异步生图配置包含PUBLIC_BASE_URL、MEDIA_PUBLIC_BASE_URL、IMAGE_TASK_RETENTION_HOURS、GENERATED_IMAGE_RETENTION_HOURS、IMAGE_TASK_REAPER_INTERVAL_SECONDS、IMAGE_TASK_LEASE_SECONDS、IMAGE_TASK_MAX_RETRIES、IMAGE_TASK_RETRY_BACKOFF_SECONDS;生产必须运行run_image_tasksworker。 - 当前 blocker:微信正式下单已能返回二维码,但线上微信回调曾出现
PaymentVerificationError,仍需单独修复并完成“付款后自动入账”闭环验收;支付宝恢复依赖开放平台把43.128.3.240加入可信 IP。线上真实标题生成已跑通并验证扣点;图片同步旧接口已由 T-612 加上游硬截止止血,T-614 已提供异步任务化路径,T-615 已补旧同步 / 新异步提交遥测和旧路弃用口径。
当前目录要点
| 路径 | 状态 | 说明 |
|---|---|---|
docs/ |
已有 | 全套 harness 文档;T-403 新增 deployment.md |
AGENTS.md / CLAUDE.md |
已有 | 仓库级入口 |
progress.md |
已有 | 执行流水,已记录多轮文档决策;后续任务继续追加 |
init.sh / init.ps1 |
已有 | 启动验证入口,已固定系统 Python 3.12 命令,并校验解释器版本 >=3.12,<3.14 |
requirements.txt / requirements-production.txt / pyproject.toml |
已有 | requirements.txt 管本地/基础运行依赖;requirements-production.txt 追加 Linux 生产 Gunicorn;pyproject.toml 落地 requires-python;T-101 新增 requests;T-102 使用既有 cryptography 做 Fernet 加密;T-501 新增 django-allauth |
config/(Django 工程) |
已有 | T-001 创建,含 settings / urls / wsgi / asgi |
apps/(users/portal/billing/ai/api/moderation) |
已有 | T-002 创建;apps/users 已定义自定义 User;T-003 已注册 admin 与 admin smoke test;T-004 已给 User.email 加唯一约束;T-101 已新增 apps/ai/providers;T-102 已新增 apps/ai/security.py、aliases.py、importers.py、management command 与 ai.0001_initial 迁移;T-103 已新增 apps/ai/audit.py 与 ai.0002_aiconfigauditlog 迁移;T-104/T-105 已新增 smoke_ai_generation 录制 title/image smoke 命令;T-201 已在 users 落 UserWallet / ApiKey,在 billing 落 PointsLedger / CallRecord;T-202 已在 billing 落 PricingRule / ExchangeRate 与 pricing.py;T-203/T-303/T-304/T-305 已在 apps/billing/services.py 落扣点/退点、余额快照、充值入账与充值下单;T-401 已在 apps/billing/services.py 落 adjust_wallet_points(),在 apps/users/admin.py 与 apps/users/templates/admin/users/userwallet/adjust_points.html 落钱包手工调点入口;T-608 已在 billing 落 SignupBonusGrant、grant_signup_bonus()、signup_bonus 流水类型、admin 检索和迁移;T-304/T-305 已在 apps/billing/payment_gateways.py 落回调验签、mock 下单与 SDK 入口;T-301~T-306 已在 api 落鉴权、生成接口编排、序列化器、图片存储、余额查询、充值回调、充值下单/状态查询、image_url SSRF 防护、生成/认证限流与统一 429 错误响应;T-501/T-608 已在 portal 落 allauth 注册/登录/登出路由、模板、adapter 与 dashboard,注册成功自动赠送 10 点;T-502 已在 portal 落 /apikeys、API Key 创建表单、列表模板与删除(吊销)动作;T-503/T-608 已在 portal 落个人中心汇总、充值记录和点数记录页;T-504 已在 portal 落 /recharge 充值页、充值表单、二维码票据展示和状态轮询;T-505 已在 portal 落本地 vendor static 与记录分页;T-601 已在 apps/ai/catalog.py 落公开模型目录,在 api 落 /api/v1/models,在 portal 落 /models 页面和导航入口;T-604 已在 moderation 落 SensitiveWord、keyword matcher、归一化、共享 cache 版本失效与 admin;T-606 已在 portal 落公开首页、DownloadRelease、下载版本 admin、brand.css 与首页模板;T-607/T-609 已在 api 落 /api/v1/client/releases/latest 公开版本检查接口,并在 portal DownloadRelease 落 force_update 字段与 admin 展示 |
apps/api 异步生图 |
已有 | T-614 已落 ImageGenerationTask、api.0001_initial、异步提交/轮询路由、任务 service、worker lease / heartbeat / reaper、run_image_tasks 命令和 admin 只读排障;T-616 已落 api.0002、next_attempt_at、临时性失败自动重试和轮询响应新增重试字段;旧同步生图接口保留 |
manage.py |
已有 | T-001 创建 |
tests/ |
待建 | 随各任务补充 |
任务看板状态
任务状态以 06-tasks.md 为准,历史执行记录见 ../progress.md。
- 已完成:T-001 初始化 Django + DRF 项目骨架;T-002 建立 apps 目录、自定义 User 与配置;T-003 接通 django-admin 与最小测试;T-004 Phase 0 骨架审核修补;T-101 Provider 适配器层 + 移植 cmbot 调用;T-102 AiModel + ModelAlias 模型 + 别名解析;T-103 配置变更审计;T-104 跑通一次录制标题生成;T-105 Phase 1 AI 层审核修补;T-201 User / UserWallet / ApiKey / PointsLedger / CallRecord 模型;T-202 PricingRule / ExchangeRate 模型 + 计费计算;T-203 并发安全扣点 / 退点;T-204 Phase 2 计费核心审核加固;T-301 API Key 鉴权;T-302 生成标题 / 图片接口;T-303 余额查询接口;T-304 充值回调;T-305 扫码充值下单 + 轮询;T-306 Phase 3 对外 API 安全加固;T-501 注册 / 登录(allauth);T-502 API Key 自助管理页;T-503 个人中心 / 记录页;T-504 充值页(扫码 + 轮询到账);T-505 Phase 4 用户端审核优化;T-401 运营后台完善;T-402 完整验收 MVP;T-403 部署 / 运行文档;T-601 可用别名发现;T-602 django-admin 中文化(第 1-3 层);T-603 django-admin 中文化(第 4 层·字段级);T-604 中文敏感词本地过滤;T-605 免邮箱验证策略落地;T-606 公开首页 + 客户端下载入口;T-607 桌面端最新版本检查接口;T-608 新用户注册赠送试用点数(当前 10 点);T-609 桌面端版本检查接口增加强制更新标记;T-610 首页导入模板下载入口;T-611 用户端品牌名统一为虾皮圈;T-612 生图同步接口止血(上游硬截止 + 长请求池校准);T-613 抽生成核心 service(计费+审核+上游共享 core);T-614 生图异步任务化接口(提交+轮询,新增不动旧接口);T-615 旧同步生图接口用量遥测 + 弃用口径;T-616 生图失败自动重试 2 次;T-617 桌面端版本检查接口增加文件大小字段;T-618 客户端发布版本后台必填文件校验元数据。
- 已完成补充:T-619 多张图片理解并返回文字;T-620 图生图支持单图 / 多图主图与参考图;T-622 图片生成任务后台图片缩略预览;T-623 图片生成任务单图 / 多图筛选;T-624 蝦皮圈设备登记与会话观测;T-625 蝦皮圈设备使用关联与迁移观测;T-626 软件套餐、权益与设备席位基础模型及凭证续期/撤销清理;T-627 存量用户迁移权益、网页确认与设备凭证;T-628 蝦皮圈专属授权入口与影子校验;T-629 软件套餐购买、续订订单与权益入账;T-630 账号订阅授权与默认多设备模式;T-631 隐藏旧设备授权模型的 admin 菜单入口;T-632 会员订阅三阶段启用、状态接口补全与 admin 简化。
- 正在进行:无。
- T-621 注册赠点运营后台配置继续留在 Backlog。真实支付回调到账闭环、客户端发布、生产多图理解模型配置和线上旧同步接口用量观察仍可继续拆任务。
- 当前 blocker:支付商户真实密钥/证书与生产 SDK 依赖仍待提供;微信回调到账闭环仍需真实支付验收;真实 AI 标题生成已在线上跑通,图片生成慢 / 504 / 客户端超时风险已拆为 T-612~T-616 并完成工程侧处理。
- 下一个可领取任务:按业务优先级从 Backlog 拆分后续任务。T-621 保留在 Backlog,真实微信商户支付验收仍是线上 blocker;软件订阅订单已完成代码与 mock/SDK 契约验证,但未进行真实付款验收。具体范围见
06-tasks.md。
当前可运行内容
# Windows PowerShell
py -3.12 -m pip install -r requirements.txt
py -3.12 manage.py check
py -3.12 manage.py test
py -3.12 manage.py runserver
py -3.12 manage.py import_ai_models path\to\ai_models.json --create-default-aliases
py -3.12 manage.py smoke_ai_generation title --recorded
py -3.12 manage.py smoke_ai_generation image --recorded
# Unix / WSL
python3.12 -m pip install -r requirements.txt
python3.12 manage.py check
python3.12 manage.py test
python3.12 manage.py runserver
python3.12 manage.py import_ai_models path/to/ai_models.json --create-default-aliases
python3.12 manage.py smoke_ai_generation title --recorded
python3.12 manage.py smoke_ai_generation image --recorded
# Linux production
python3.12 -m pip install -r requirements-production.txt
python3.12 manage.py migrate
python3.12 manage.py createcachetable cmhub_cache
python3.12 manage.py collectstatic --noinput
gunicorn config.wsgi:application --bind 127.0.0.1:8001 --workers 2 --worker-class gthread --threads 4 --timeout 120
gunicorn config.wsgi:application --bind 127.0.0.1:8002 --workers 1 --worker-class gthread --threads 4 --timeout 360
python3.12 manage.py run_image_tasks --worker-id cmhub-image-worker-1 --sleep-seconds 1
当前对外 API:
POST /api/v1/generate/titlePOST /api/v1/analyze/imagesPOST /api/v1/client/devices/registerPOST /api/v1/client/devices/heartbeatPOST /api/v1/generate/imagePOST /api/v1/generate/image/tasksGET /api/v1/generate/image/tasks/{task_id}GET /api/v1/balanceGET /api/v1/modelsGET /api/v1/client/releases/latestGET /api/v1/cmshopee/subscription/statusPOST /api/v1/recharge/create(用户端 session + CSRF)GET /api/v1/recharge/status(用户端 session)POST /api/v1/recharge/callback/wechatPOST /api/v1/recharge/callback/alipay
当前用户端页面:
GET /GET/POST /signupGET/POST /loginGET/POST /logoutGET /dashboardGET/POST /rechargeGET/POST /apikeysPOST /apikeys/<id>/deleteGET /modelsGET /records/rechargeGET /records/usage
当前骨架可运行。T-002 已在首次迁移前创建自定义 User,并按 env.md 接入 MySQL 8.4 / utf8mb4;远程 MySQL 已完成 Django 初始迁移。T-003 已接通 django-admin,测试可创建/销毁 test_cmhub 测试库;当前远程 MySQL 对频繁建库/销库仍可能间歇超时,必要时用 --keepdb 且串行跑测试。T-004 已应用 users.0002_alter_user_email,user.email 已有唯一索引。T-101 的 AI provider 层只做 HTTP 调用与响应解析;T-102 已把 provider 运行配置接到数据库 AiModel / ModelAlias,resolve_alias() 每次查当前 active 配置并按 text / image 能力校验。T-103 已补 AiConfigAuditLog,admin 保存/删除 AiModel / ModelAlias 时记录 actor、action、target、changed_fields、changes、created_at,密钥只记录 empty/set 状态。T-104/T-105 已用临时回滚配置跑通录制标题和录制图片生成。T-201 已落地钱包、API Key、点数流水和调用记录:API Key 明文只在创建 helper 返回,库内只存 hash/prefix;CallRecord 只存 result_ref/result_summary,没有 provider raw 字段。T-202 已落地 PricingRule / ExchangeRate:计费按 operation_type + alias + resolution 查 active 规则,优先精确分辨率,再回退默认价;缺规则抛 NoPricingRuleError(code="no_pricing_rule");金额换点数按当前 active 汇率向下取整。T-203 已落地 precharge_call() / mark_call_success() / refund_call_points():预扣锁钱包行,余额不足不写调用/流水;失败退点锁调用记录并幂等写 refund 流水。T-204 已完成复合唯一约束加固,并取得一次完整 manage.py test 单次全绿。T-301 已落地 Authorization: Bearer <API_KEY> 鉴权:成功后 request.user 为所属用户、request.auth 为 ApiKey,缺失/无效 Key 返回 401,用户或 Key 禁用返回 403,外部 API 不接受 Web session。T-302/T-613 已落地生成接口与共享核心:旧同步接口仍保持原响应契约;prepare_generation() 执行 prompt 审核、图片输入处理、别名解析、Provider 选择和计费计算;precharge_generation() 调 billing 预扣;execute_precharged_generation() 复用已预扣 CallRecord 调上游并成功确认或失败退点;图片结果保存到本地 media 并通过 URL 构建器返回外部 URL。T-303 已落地余额查询接口:GET /api/v1/balance 继承外部 API Key 鉴权,读取 billing 余额快照并返回兼容字段 user / points_balance,以及不含邮箱的 account.username / account.display_name,测试覆盖余额与流水累加一致。T-304 已落地充值回调:RechargeOrder 保存下单锁定的金额/汇率/点数,微信/支付宝回调先验签再按订单幂等入账,重复回调不重复加点,金额不一致不入账;主动查单兜底可调用 query_and_apply_recharge_payment(order_no, query_func) 复用同一入账路径。T-305 已落地扫码下单与轮询:用户端 session 登录后可 POST /api/v1/recharge/create 创建 pending 订单并拿到 mock/SDK 二维码票据,GET /api/v1/recharge/status 只返回本人订单并在 pending 时尝试主动查单补入账;API Key 不能调用这两个用户端接口。T-306 已落地对外 API 安全加固:image_url 下载在扣点前做协议白名单、公网地址校验、重定向逐跳校验和响应大小上限;DRF 全局默认不再隐式启用 Session/Basic;生成接口按 Key 限流,认证失败按 IP 限流;充值下单有单笔金额上限。T-501/T-605/T-608 已落地 allauth 注册 / 登录:ACCOUNT_EMAIL_VERIFICATION="none",免邮箱验证、注册即可用,邮箱仍必填且唯一;注册成功经 billing 发放 10 点并写 signup_bonus 流水,重复调用或并发触发由 SignupBonusGrant 幂等标记兜底,注册限流由 allauth signup rate limit 执行。T-502 已落地 API Key 自助管理:/apikeys 登录访问,生成后完整明文只显示一次,列表只显示 prefix,不显示 hash 或历史明文;删除为吊销 revoked,吊销后外部 API 返回 403。T-503/T-608 已落地个人中心与记录页:/dashboard 展示剩余点数、充值总额、获得点数、净消耗点数和最近记录;/records/recharge 展示当前用户充值订单;/records/usage 展示当前用户 signup_bonus/consume/refund 点数流水并关联调用信息;所有页面均只读且只查本人。T-504 已落地充值页:/recharge GET 展示余额、充值表单、当前订单和最近充值,POST 创建 pending 订单并展示二维码票据,浏览器轮询 /api/v1/recharge/status,paid 后刷新页面重新读取余额;页面不直接写钱包或流水。T-401 已落地运营后台完善:用户列表显示钱包余额,钱包余额只读且通过专用表单手工调点,调点必须填原因、非 0、不得扣成负数,并经 adjust_wallet_points() 锁钱包写 PointsLedger(adjust);API Key admin 只展示 prefix 和 hash 摘要,不回显明文或完整 hash;订单、流水、注册赠点记录、调用记录继续只读并增强检索。T-402 已完成 MVP P0 验收并新增 docs/mvp-acceptance.md。T-403 已完成部署 / 运行文档,生产按 deployment.md 执行,并已补 settings 对生产静态目录、共享 cache、CSRF trusted origins、HTTPS cookie/proxy/HSTS 与注册限流的环境变量支持。T-601 已落地可用别名发现:GET /api/v1/models 用 API Key 鉴权返回公开别名目录,/models 用 session 展示只读「可用模型」页;两者均不解密 provider key,不输出底层 SKU、URL、key 或 extra_body。T-603 已完成 django-admin 字段级中文化并人工确认字段标签中文。T-604 已落地本地 prompt 敏感词过滤:MODERATION_ENABLED=false 默认 no-op,启用 keyword 后命中返回 content_blocked,并在下载 image_url、解析别名、计费、预扣点和上游调用前拦截。T-606 已落地公开首页:GET / 匿名 200、不跳登录;下载区读取 Windows 当前 DownloadRelease,优先 external_url,无当前版本显示「暂未发布」;现有 portal 页面已共用 brand.css 品牌 token。T-607/T-609 已落地公开版本检查接口:GET /api/v1/client/releases/latest 匿名 200,无需 API Key;支持 windows/macos/linux,返回当前版本 JSON 或 release:null,当前版本响应包含 release.force_update。真实标题上游生成已在线上跑通并验证扣点;图片生成真实耗时仍需补测。
T-614 已落地异步生图任务化:提交接口预扣后返回 task_id,轮询接口返回 queued/running/succeeded/failed,worker 和 reaper 复用同一套成功确认 / 失败退点路径,旧同步接口继续兼容。当前 worker 会复跑审核 / 别名解析 / 定价,但不重复扣点;image_url 输入会在 submit 阶段下载,桌面端主链路应优先用 image_base64。T-615 已落地旧同步 / 新异步提交遥测:两个入口都会写 generation_route_usage 结构化日志,便于按客户端版本、API Key 和 route_type 观察迁移进度;旧同步接口下线前必须继续保持响应兼容,并单独立下线任务。
T-619 已落地同步多图理解:调用方提交有序 images 列表,服务按 vision + alias 默认价固定扣点,成功返回文字,失败幂等退款;输入图片和 provider raw 不写入调用记录。代码部署并迁移后,需由运营配置视觉模型、默认别名与默认价格,才会成为可调用能力。
T-632 已落地会员订阅三阶段模式:CMSHOPEE_SUBSCRIPTION_MODE=open 为当前开发测试默认值,无需给所有用户逐个绑定长期权益;shadow 继续放行并记录真实权益覆盖,enforce 才按真实权益拦截产品专属 submit。订阅状态接口已补齐桌面端账号、套餐、顶层有效期、会员中心与通知字段;admin 软件授权首页只显示“会员套餐”和“用户会员”,隐藏模型及历史数据未删除。
开始编码前检查
- 读仓库级
AGENTS.md/CLAUDE.md。 - 读
docs/00-ai-start-here.md。 - 读
docs/05-coding-rules.md(尤其第 8 节资金安全)。 - 在
docs/06-tasks.md领取第一个TODO且依赖均DONE的任务;当前没有可直接领取的任务。 - 当前开发测试环境应保持
CMSHOPEE_SUBSCRIPTION_MODE=open;切到shadow/enforce前须补跑数据库集成测试,并用真实微信商户完成充值和订阅两条回调闭环验收。
维护规则
代码状态变化时同步更新本文:新增/移动入口文件、初始化框架或模块、任务状态变化、新增可运行命令、发现文档与代码不一致。
- 任务状态变化同步
06-tasks.md。 - 每轮执行记录、验证命令、阻塞、决策追加到
../progress.md。 - 本文件只保留当前快照,不保留完整历史。