--- date: "2026-06-01" topic: geo-tech-debt-cleanup --- ## Summary GEO 平台技术债清理冲刺,分三批交付:第一批修复 29 个模型文件中 73 个缺失 `DateTime(timezone=True)` 的 datetime 列(按 API 调用路径优先级排序);第二批统一前端 2 个页面组件的 API 客户端调用;第三批完成前端端到端验证和部署安全加固。每批有明确交付物和验证门。 ## Problem Frame Plan 004 的端到端验证暴露了一个系统性问题:asyncpg 驱动严格检查 timezone-aware datetime 与 `TIMESTAMP WITHOUT TIME ZONE` 列的兼容性,任何写入 `datetime.now(UTC)` 到未标记 timezone 的列都会直接报运行时错误。当前仅修复了变现闭环涉及的 4 个核心表(diagnosis_records、payment_orders、subscriptions、users),其余 29 个模型文件的 73 个列仍是确定的运行时炸弹。与此同时,前端 2 个页面组件绕过统一 API 客户端直接调用 `fetch`,认证 token 不被附加,用户访问会 401。Docker 部署从未验证成功,Redis/PostgreSQL 安全配置缺失。这些技术债不清理,系统无法真正上线。 ## Key Decisions **时区修复按 API 调用路径优先级排序,而非一次性全量迁移。** 全量迁移风险高(73 列同时 ALTER TABLE),且部分 API 路径尚未被触发。按实际调用路径修复,每批修完验证对应 API 可用,风险可控。 **前端 API 客户端统一排在时区修复之后。** 401 错误是确定的问题但影响范围有限(2 个页面),时区 bug 影响所有涉及 datetime 写入的 API。先修高影响再修低影响。 **部署安全加固排在最后。** 安全配置(Redis 密码、PostgreSQL 弱密码、.env.production)在本地开发环境不影响功能,但上线前必须完成。作为第三批交付。 **前端 E2E 验证与部署安全加固合并为第三批。** E2E 验证需要浏览器环境,与部署配置调整可以并行进行。 ## Requirements **时区修复(Batch 1)** R1. 所有 29 个模型文件的 73 个 datetime 列添加 `DateTime(timezone=True)`,PostgreSQL 对应列类型改为 TIMESTAMPTZ R2. 时区修复按 API 调用路径分三批执行:核心变现路径(brand、query、citation_record、attribution_record、content、geo_plan、suggestion)→ Agent 框架路径(agent、detection_task、monitoring、monitoring_record、competitor_insight、trend_insight)→ 辅助路径(knowledge、knowledge_graph、organization、lifecycle、distribution、alert、alert_setting、platform_rule、platform_rule_version、usage_record、api_key、query_task、brand_knowledge、competitor) R3. 每批修复后验证对应 API 路径可正常写入和读取 datetime 数据 R4. 生成对应的 Alembic 迁移脚本,迁移可从当前数据库状态执行 **前端 API 客户端统一(Batch 2)** R5. `reports/page.tsx` 的 CSV 导出改用统一 API 客户端,认证 token 正确传递 R6. `lifecycle/new/page.tsx` 的项目创建改用统一 API 客户端,认证 token 正确传递 R7. 统一 API 客户端支持非 JSON 响应(如 blob/PDF 导出),避免 `reports.ts` 等模块被迫绕过 **前端端到端验证(Batch 3)** R8. 浏览器中可完成完整变现闭环:注册→登录→创建品牌→诊断→查看健康分→付费墙→支付→解锁 R9. 公开健康分页面无需登录即可访问并生成报告 R10. Onboarding 流程在浏览器中可正常走通 **部署安全加固(Batch 3)** R11. Redis 配置密码保护,非本地环境禁止无密码连接 R12. PostgreSQL 默认弱密码更换为强密码 R13. 创建 `.env.production` 模板,包含所有生产环境必需配置项 R14. Docker Compose 部署验证通过,4 个服务均可正常启动和通信 ## Key Flows - F1. 时区修复验证流程 - **Trigger:** 某批模型文件完成 DateTime(timezone=True) 修改 - **Steps:** 修改模型 → 生成 Alembic 迁移 → 执行迁移 → 调用对应 API 写入数据 → 验证写入成功 → 读取数据验证时区正确 - **Outcome:** 该批 API 路径的 datetime 读写不再触发 asyncpg 时区错误 - **Covers:** R1, R2, R3, R4 - F2. 前端变现闭环验证流程 - **Trigger:** 浏览器打开 GEO 平台 - **Steps:** 注册→登录→创建品牌→触发诊断→查看健康分→尝试付费功能→触发付费墙→Mock支付→功能解锁→验证 reports 和 lifecycle 页面正常 - **Outcome:** 用户在浏览器中完成从获客到付费的完整链路,所有页面认证正常 - **Covers:** R5, R6, R8, R9, R10 ## Scope Boundaries **In scope:** - 29 个模型文件的 DateTime(timezone=True) 修复 - 对应 Alembic 迁移生成和执行 - 前端 2 个页面组件 API 客户端统一 - 统一 API 客户端非 JSON 响应支持 - 浏览器端到端验证 - Docker Compose 部署验证 - Redis/PostgreSQL 安全配置 - .env.production 模板 **Deferred for later:** - 真实微信/支付宝 SDK 接入 - CI/CD 流水线 - 性能优化和压力测试 - 生产环境域名和 HTTPS 配置 - 完整测试覆盖 - pgvector 镜像优化(改用 pgvector/pgvector:pg15) - JWT_SECRET 强密钥生成 **Outside this sprint:** - UI 打磨和视觉优化 - 新功能开发 - 代码重构(除时区修复外) ## Dependencies / Assumptions - PostgreSQL 15 + pgvector 扩展可用(Plan 004 已验证) - Redis 7 可用(Plan 004 已验证) - asyncpg 驱动严格时区检查行为不变(这是正确行为,不是 bug) - 已修复的 4 个核心表(diagnosis_records、payment_orders、subscriptions、users)不需要再次修改 - `monitoring.py` 和 `monitoring_record.py` 可能存在重复模型定义,需确认哪个是实际使用的 - Docker Hub 网络问题可能影响 Docker 部署验证(Plan 004 中曾因此失败) ## Outstanding Questions **Resolve Before Planning:** - `monitoring.py` 和 `monitoring_record.py` 都定义了 MonitoringRecord 和 ContentBaseline,需确认哪个是实际使用的,避免重复修复 **Deferred to Planning:** - Alembic 迁移策略:是生成一个大的迁移脚本还是按批次生成多个 - 统一 API 客户端非 JSON 响应的具体实现方式(扩展 fetchWithAuth 还是新增 fetchWithAuthBlob) - Docker 部署验证是否需要解决 Docker Hub 网络问题(镜像源配置等) ## Sources / Research - Plan 004 端到端验证记录:时区 bug 在 diagnosis_records 和 payment_orders 上的具体表现 - `backend/app/models/` — 29 个待修复模型文件,73 个 datetime 列 - `frontend/lib/api/client.ts` — 统一 API 客户端,导出 fetchWithAuth 和 API_BASE - `frontend/app/(dashboard)/dashboard/reports/page.tsx` — 绕过统一客户端,手动 fetch + Authorization header - `frontend/app/(dashboard)/dashboard/lifecycle/new/page.tsx` — 绕过统一客户端,手动 fetch + Authorization header - `frontend/lib/api/reports.ts` — PDF blob 导出被迫绕过统一客户端(fetchWithAuth 只返回 JSON) - `docker-compose.yml` — Redis 无密码、PostgreSQL 弱密码(geo:geo123) - `docker-compose.prod.yml` — 依赖不存在的 .env.production