diff --git a/docs/06-tasks.md b/docs/06-tasks.md index 850d59d..8b83b96 100644 --- a/docs/06-tasks.md +++ b/docs/06-tasks.md @@ -57,6 +57,10 @@ | T-222 | 货运信息存储、API 与 Admin 页面 | T-221 | Go 后端幂等保存同步记录、货运单和明细;Admin 可按单号导入、列表和查看 | | T-223 | 待采购需求提取与任务生成 | T-222 | 一条有效商品明细形成一条可复核采购需求;参考图齐备后幂等生成采购任务 | | T-224 | ERP 日期增量同步 | T-223 | 按 ERP 创建日期区间分页同步,重叠窗口去重;失败不推进成功水位 | +| T-225 | 冻结 Go 直连 ERP 协议与安全边界 | T-224 | 以脱敏 fixture 固定验证码、登录、查询和归一化契约;不访问线上 ERP | +| T-226 | Go ERP 会话管理与 Admin 验证码登录 | T-225 | 后端内存维护受控会话;Admin 人工输入验证码,不暴露账号密码或 Cookie | +| T-227 | Go 直连顺运宝查询接入货运同步 | T-226 | `FreightSource` 直接查询 ERP,保留单号/日期异步同步、幂等和错误边界 | +| T-228 | 移除 Python ERP Connector 并完成切换 | T-227 | 删除 Connector、端口和共享 API Key;单 Go 后端完成离线回归与真实登录 smoke | ## Phase 3:端到端验证 diff --git a/docs/current-state.md b/docs/current-state.md index 31609a3..52d6052 100644 --- a/docs/current-state.md +++ b/docs/current-state.md @@ -186,8 +186,8 @@ - 已完成:另含 T-220 至 T-224 ERP 契约、Connector、货运存储、采购需求生成和 日期增量同步。 - 进行中:无。 -- 下一步:进入 T-301 P0 UI 完整交互验收;真实 ERP 上线前仍需确认开放 API、 - 数据使用权限并由人员完成验证码登录。 +- 下一步:T-225 至 T-228 将把顺运宝 Python Connector 收敛到 Go 后端;真实 ERP + 上线前仍需确认开放 API、数据使用权限并由人员完成验证码登录。 ## 当前可运行内容 diff --git a/docs/tasks/T-225.md b/docs/tasks/T-225.md new file mode 100644 index 0000000..e7cc7ba --- /dev/null +++ b/docs/tasks/T-225.md @@ -0,0 +1,63 @@ +--- +id: T-225 +title: 冻结 Go 直连 ERP 协议与安全边界 +phase: 2 +deps: + - T-224 +status: TODO +created: 2026-07-29 +context_ref: d62a4af +work_branch: null +write_paths: + - docs/tasks/T-225.md + - docs/03-tech-stack.md + - docs/04-architecture.md + - docs/05-coding-rules.md + - docs/integrations/shunyunbao-contract.md + - backend-api/internal/platform/shunyunbao/** + - backend-api/internal/platform/erpconnector/** +--- + +## 问题 / 背景 + +T-221 至 T-224 把顺运宝协议收敛在 Python Connector,导致单机 Admin 还要维护 +Python 环境、loopback 端口和与 Go 后端相同的服务密钥。当前 `ERP_CONNECTOR_NOT_CONFIGURED` +证明这组额外进程边界会成为日常操作失败点。迁移前必须先固定 Go 实现的协议、字段和 +安全界限,不能按猜测重写私有 ERP 请求。 + +## 关联需求与交互 + +- 功能:F-011、F-012。 +- 用户故事:US-011、US-012。 +- 交互:IX-012、IX-013;本任务不新增可操作页面。 +- 架构:Go `FreightSource` 保持为货运用例的唯一上游边界,顺运宝实现移至 + `internal/platform/shunyunbao`。 + +## 方案 + +1. 以现有脱敏 fixture 和已验证脚本为依据,在 Go 中固定验证码、登录、用户校验、 + 完整单号、日期范围、分页和 `listByStock` 请求/响应契约。 +2. 只保留下游 allowlist 规范化对象;收件人、电话、详细地址、Cookie、JWT、密码、 + 验证码和原始响应不得进入数据库、日志、错误消息、fixture 或 VLM。 +3. 验证码固定由人员读取和输入。不得迁移本地 OCR 自动识别、自动重试绕过验证码或 + 对外暴露 ERP 会话。 +4. 统一来源错误为未配置、会话失效、未找到、协议异常和暂时不可用;用例层不再依赖 + Python Connector 包定义的错误变量。 +5. 本任务只建立 Go 契约、脱敏测试和接口边界,不切换运行时查询路径。 + +## 验收要点 + +- [ ] Go fixture 测试固定请求 header、查询条件、分页、详情批量和 allowlist 归一化。 +- [ ] 负向测试证明 PII、Cookie、JWT、账号、密码和验证码不会出现在输出或错误中。 +- [ ] 取消 OCR、Redis 和 Python HTTP 服务作为 Go 第一版运行时依赖的设计。 +- [ ] 不访问线上 ERP;现有 Python Connector 仍可继续运行,货运导入行为不改变。 + +## 边界 + +- 不修改 Admin 页面、SQLite schema、采购任务生成或拼多多流程。 +- 不把 Python 请求脚本逐行翻译为业务 handler。 +- 不删除 `erp-connector/`;删除属于 T-228。 + +## 执行记录 + +- 2026-07-29:由 `d62a4af` 创建,等待 T-224 后开始。 diff --git a/docs/tasks/T-226.md b/docs/tasks/T-226.md new file mode 100644 index 0000000..96aed1a --- /dev/null +++ b/docs/tasks/T-226.md @@ -0,0 +1,64 @@ +--- +id: T-226 +title: Go ERP 会话管理与 Admin 验证码登录 +phase: 2 +deps: + - T-225 +status: TODO +created: 2026-07-29 +context_ref: d62a4af +work_branch: null +write_paths: + - docs/tasks/T-226.md + - docs/04-architecture.md + - docs/api.md + - docs/routes.md + - docs/current-state.md + - backend-api/internal/config/** + - backend-api/internal/platform/shunyunbao/** + - backend-api/internal/transport/httpapi/** + - backend-api/internal/transport/webui/** + - backend-api/cmd/api/** +--- + +## 问题 / 背景 + +直接 Go 查询需要让后端在同一 ERP 会话中获取验证码、登录、验证状态和发起查询。账号 +密码不能输入到普通 Admin 表单,Cookie/JWT 不能发给浏览器;同时单机验证版不需要为 +恢复会话额外部署 Redis。 + +## 关联需求与交互 + +- 功能:F-011。 +- 用户故事:US-011。 +- 交互:IX-012 增加 ERP 连接状态、获取验证码和提交验证码。 +- 架构:一个受互斥保护的 Go 会话管理器服务一个受配置 ERP 账号;进程重启后会话失效, + 需要人员重新登录。 + +## 方案 + +1. ERP base URL、用户名和密码只从后端启动环境读取;不读取 `.env`,不保存到 SQLite、 + Cookie、浏览器、普通日志或 API 响应。 +2. Admin 连接页显示匿名会话状态,可请求一次性验证码图片并输入验证码登录。图片响应 + 必须 `no-store`,浏览器只得到验证码图片和短期 ticket,不能得到 ERP Cookie/JWT。 +3. 会话管理器为 Cookie jar、token、用户最小标识和 ticket 建立串行锁;查询、验证码 + 和登录不能并发改变同一会话。 +4. 账号/密码未配置、验证码过期、登录拒绝、会话过期和 ERP 不可用均返回稳定匿名错误。 +5. 首版只保留内存会话;加密持久化会话须另立任务,不引入 Redis。 + +## 验收要点 + +- [ ] 配置缺失、验证码获取、错误/过期验证码、登录成功、会话过期和并发请求有单元/HTTP 测试。 +- [ ] Admin 页面在桌面和手机视口显示状态、验证码和可修复错误,不显示密码、Cookie、JWT 或验证码文本。 +- [ ] 会话请求和查询共享同一受控 Cookie jar;进程重启后明确要求重新登录。 +- [ ] `go test ./...`、`go vet ./...` 通过;不访问线上 ERP。 + +## 边界 + +- 不自动 OCR、猜测或绕过验证码。 +- 不实现多 ERP 账号、多租户、Redis 或凭证 Web 编辑。 +- 不切换货运同步查询源;属于 T-227。 + +## 执行记录 + +- 2026-07-29:由 T-225 依赖创建,等待协议契约完成。 diff --git a/docs/tasks/T-227.md b/docs/tasks/T-227.md new file mode 100644 index 0000000..93cfc8e --- /dev/null +++ b/docs/tasks/T-227.md @@ -0,0 +1,67 @@ +--- +id: T-227 +title: Go 直连顺运宝查询接入货运同步 +phase: 2 +deps: + - T-226 +status: TODO +created: 2026-07-29 +context_ref: d62a4af +work_branch: null +write_paths: + - docs/tasks/T-227.md + - docs/04-architecture.md + - docs/api.md + - docs/current-state.md + - backend-api/cmd/api/** + - backend-api/internal/platform/shunyunbao/** + - backend-api/internal/usecase/** + - backend-api/internal/transport/httpapi/** + - backend-api/internal/transport/webui/** + - backend-api/internal/config/** +--- + +## 问题 / 背景 + +T-226 能在 Go 后端建立受控 ERP 会话,但货运同步仍通过 Python Connector。需要将 +`FreightSource` 的运行时实现替换为 Go 直连客户端,同时完整保留 T-222 至 T-224 的 +异步同步、幂等、日期窗口、水位、revision 与采购需求语义。 + +## 关联需求与交互 + +- 功能:F-011、F-012。 +- 用户故事:US-011、US-012。 +- 交互:IX-012、IX-013;现有“按完整单号”“按创建日期”“同步至现在”入口不变。 +- 架构:`FreightService` 后台同步继续只依赖 `FreightSource`,Go 顺运宝实现直接调用 + 外部 HTTPS,不经 loopback HTTP 或共享服务密钥。 + +## 方案 + +1. 将 Go 顺运宝 source 注入 API 进程;查询前验证会话,按完整单号或 Asia/Shanghai + 日期范围执行有界分页和详情批量读取。 +2. 保留既有同步记录和异步执行:浏览器只创建同步 run,后台工作执行外部请求,进程 + 中断后的 RUNNING run 仍按现有规则恢复为稳定失败。 +3. 复用 T-225 allowlist 归一化;响应不完整、超限、重复外部身份冲突或会话失效均整批 + 失败,不保存半批数据、不推进水位。 +4. 单 ERP 账号同步使用有界串行执行,避免登录/验证码与查询竞争;不增加无界 goroutine + 或系统级队列。 +5. 真实验证只在人员已配置凭证并完成验证码登录后按单号执行一次;测试和开发使用 + `httptest` 伪 ERP。 + +## 验收要点 + +- [ ] 完整单号、日期范围、重叠水位、分页去重、详情多商品、失败不推进水位均有 Go 集成测试。 +- [ ] Admin 输入单号后创建异步 run,并由 Go source 直接得到相同规范化货运/明细结果。 +- [ ] 缺会话显示 `ERP_SESSION_REQUIRED`;不再出现 Connector URL/API Key 相关错误。 +- [ ] 真实受控单号 smoke 可选且不记录订单内容;未具备凭证时明确标记未运行。 +- [ ] `go test ./...`、`go test -race ./...`、`go vet ./...` 通过。 + +## 边界 + +- 不改变商品采购状态判定、参考图上传和采购任务生成。 +- 不将 ERP 原始图片引用解释为可访问 URL。 +- 不删除 Python Connector;切换清理属于 T-228。 + +## 执行记录 + +- 2026-07-29:由 T-226 依赖创建,等待 Admin 会话能力完成。 diff --git a/docs/tasks/T-228.md b/docs/tasks/T-228.md new file mode 100644 index 0000000..b08f06a --- /dev/null +++ b/docs/tasks/T-228.md @@ -0,0 +1,72 @@ +--- +id: T-228 +title: 移除 Python ERP Connector 并完成 Go 切换 +phase: 2 +deps: + - T-227 +status: TODO +created: 2026-07-29 +context_ref: d62a4af +work_branch: null +write_paths: + - docs/tasks/T-228.md + - docs/00-ai-start-here.md + - docs/03-tech-stack.md + - docs/04-architecture.md + - docs/05-coding-rules.md + - docs/06-tasks.md + - docs/api.md + - docs/current-state.md + - docs/integrations/** + - README.md + - backend-api/README.md + - backend-api/cmd/api/** + - backend-api/internal/config/** + - backend-api/internal/platform/erpconnector/** + - erp-connector/** + - scripts/start-erp-connector.bat + - start-backend.bat + - init.ps1 +--- + +## 问题 / 背景 + +Go 直连 source 经 T-227 验证后,保留 Python Connector、8091 loopback 端口、服务密钥、 +启动脚本和双份协议实现只会造成漂移与错误配置。需要受控删除旧路径,并把启动、文档和 +验证统一为单一 Go 后端。 + +## 关联需求与交互 + +- 功能:F-011、F-012。 +- 用户故事:US-011、US-012。 +- 交互:IX-012、IX-013;页面入口保持不变。 +- 架构:运行时只保留 Go API 进程直接访问 ERP;外部 ERP 仍是受控边界。 + +## 方案 + +1. 删除仓库内 `erp-connector/`、Connector 启动脚本、HTTP client、`CMROUBAO_ERP_CONNECTOR_*` + 配置和共享 API Key 文档。 +2. 保留外部原始研究脚本 `D:\chengma\shunyunbaoerp\shunyunbaoerp_single.py` 不受仓库 + 删除影响;它不是运行时依赖。 +3. 统一启动脚本为 Go 后端环境校验和启动;ERP 未配置或会话失效时 Admin 提供可修复 + 会话状态,而不是在输入单号后才暴露 Connector 配置错误。 +4. 删除前运行全仓引用扫描、Go 测试/race/vet、根验证和隔离 SQLite/Gin smoke;保留 + 脱敏 fixture,不保留真实 Cookie、订单号或 HAR。 + +## 验收要点 + +- [ ] 仓库不再包含 Python Connector、8091 监听、Connector API Key 或其启动命令。 +- [ ] Go 后端在 ERP 凭证缺失、未登录和伪 ERP 成功路径下均返回稳定、可操作状态。 +- [ ] `rg` 证明已跟踪文件无 Connector 运行时引用、真实凭证、Cookie、JWT 或订单样本。 +- [ ] `go test ./...`、`go test -race ./...`、`go vet ./...` 和根验证通过。 +- [ ] 文档只说明单 Go 后端、人工验证码和外部 ERP 风险;真实线上 smoke 结果明确记录。 + +## 边界 + +- 不删除工作区外的原始 Python 研究脚本或用户私有 HAR。 +- 不自动登录、自动 OCR 或无人值守定时同步。 +- 不改变 Admin/采购任务的授权、下单和付款边界。 + +## 执行记录 + +- 2026-07-29:由 T-227 依赖创建,等待 Go 查询链路验收后进行删除。