feat(t229): load ERP credentials from dotenv

This commit is contained in:
QiuSW
2026-07-29 10:25:56 +08:00
parent d75a7d8dc0
commit f0fbdbaddc
12 changed files with 396 additions and 26 deletions
+4 -2
View File
@@ -107,8 +107,10 @@
发起任意网络请求。候选图片使用鉴权、解码、大小/像素/哈希和脱敏受控上传。
- Go 命令固定 `GOTOOLCHAIN=local`;`go.mod` 不得出现更高 Go 版本或未固定的
`@latest` 依赖。
- 后端不得自动加载 `.env`、默认开启 CORS、使用包级数据库单例,或在库、handler、
健康检查中调用 `log.Fatal`/`os.Exit`。
- 后端默认不得加载 `.env`。唯一例外是 `cmd/api` 在读取配置前,以有界、allowlist 解析器
将 `backend-api/.env` 中三个 ERP 值作为进程环境变量的回退;不得修改全局环境、加载
`authctl`/数据库/HTTP/TLS 配置或接受任意路径。后端不得默认开启 CORS、使用包级数据库
单例,或在库、handler、健康检查中调用 `log.Fatal`/`os.Exit`。
- `http.Server` 必须配置 read-header/read/write/idle/header 上限和有界关闭;
recovery 不得把 Authorization、Cookie、panic 或请求正文写普通日志。
- SQLite 数据文件必须位于被忽略目录,启用 foreign keys、有限 busy timeout 和
+6 -3
View File
@@ -209,7 +209,7 @@ Cookie。它们只管理单个后端进程内的顺运宝会话,不创建货
| `GET /api/v1/erp-session` | 返回 `configured`、`authenticated`、`captcha_ready` 三个布尔状态。 |
| `POST /api/v1/erp-session/captcha` | 同一服务端 Cookie jar 获取一次验证码,返回短期 `captcha_ticket` 和仅供当前 ADMIN 读取图片的 `captcha_url`。 |
| `GET /api/v1/erp-session/captcha/{ticket}` | 返回 `image/*` 验证码,始终 `Cache-Control: no-store`。ticket 过期或不匹配返回稳定匿名错误。 |
| `POST /api/v1/erp-session/login` | 仅接受 `{"captcha_ticket":"...","captcha_code":"..."}`,使用启动环境中的账号/密码完成登录和用户校验。 |
| `POST /api/v1/erp-session/login` | 仅接受 `{"captcha_ticket":"...","captcha_code":"..."}`,使用受控本地配置中的账号/密码完成登录和用户校验。 |
成功状态响应不包含 ticket,验证码接口以外也不会返回验证码图片。稳定错误为
`ERP_NOT_CONFIGURED`、`ERP_SESSION_REQUIRED`、`ERP_CAPTCHA_INVALID`、
@@ -217,14 +217,17 @@ Cookie。它们只管理单个后端进程内的顺运宝会话,不创建货
正文或凭证。管理员 Web 的等价入口为 `/erp`、`/erp/captcha` 和 `/erp/login`,表单没有
账号或密码字段。
启动环境变量:
ERP 配置来源:
- `CMROUBAO_SHUNYUNBAO_URL`:默认 `https://www.shunyunbaoerp.com`;只接受无路径、
userinfo、query 或 fragment 的 HTTPS origin。
- `CMROUBAO_SHUNYUNBAO_USERNAME` 与 `CMROUBAO_SHUNYUNBAO_PASSWORD`:必须同时设置;
为空时连接页明确显示未配置,服务进程仍可用于其他本地功能。
- `cmd/api` 只把标准工作目录 `backend-api/.env` 中的上述三个值作为回退。系统环境变量
优先;文件缺失不报错。该解析器不修改全局环境,不加载数据库、HTTP、TLS 或 authctl
密码,也不支持变量展开、命令执行或任意路径。
会话不写 SQLite、不加载 `.env`、不使用 OCR 或 Redis;服务重启后必须重新人工登录。
会话不写 SQLite、不使用 OCR 或 Redis;服务重启后必须重新人工登录。
### `POST /api/v1/freight-syncs`
+13 -10
View File
@@ -5,7 +5,7 @@
## 当前快照
- 日期:2026-07-29
- 阶段:T-229 待增加受控 `backend-api/.env` ERP 凭证加载;随后进行人工验证码登录 smoke
- 阶段:T-229 已完成受控 `backend-api/.env` ERP 凭证加载;随后进行人工验证码登录 smoke
- Git:当前分支为 `main`;T-001 至 T-004、T-101 至 T-104、T-201 至 T-219
均按文档提交、实现提交的顺序纳入历史
- 生产代码:`android-buyer/` 已接入 Roubao Android 源码
@@ -20,8 +20,9 @@
- ERP Go 迁移:T-225 已用脱敏 fixture 固定 `internal/platform/shunyunbao` 的 header、
单号/日期查询、分页、详情批量和字段 allowlist,并使货运用例依赖来源中立错误。T-226
已增加受锁保护的 Go 内存 Cookie jar、验证码 ticket、登录和用户校验,以及 ADMIN 的
`/erp` 页面/API;账号密码仅由 `CMROUBAO_SHUNYUNBAO_*` 启动环境读取,重启后需人工
重新登录。T-227 已将其作为 `FreightSource`,查询先校验会话、再执行有界分页/详情
`/erp` 页面/API;账号密码可由 `backend-api/.env` 的受控 `CMROUBAO_SHUNYUNBAO_*`
回退提供,进程环境变量优先,重启后需人工重新登录。T-227 已将其作为 `FreightSource`,
查询先校验会话、再执行有界分页/详情
批量并返回 allowlist;T-228 已删除旧 Python Connector、loopback 端口和共享 API Key;
未访问真实 ERP。
- ERP 增量同步:v14 支持 Asia/Shanghai 创建日期闭区间和“同步至现在”,source 单窗
@@ -35,7 +36,7 @@
- Android Studio:未安装;`winget` 静默安装卡住后已终止,不阻塞命令行构建
- 测试:T-219 Android Debug/Release 单元测试与构建和根 `init.ps1` 通过;
Debug APK `1.4.16 (21)` 已覆盖安装到 PKG110
- 后端测试:T-226 至 T-228 已运行 `go test ./...`、`go test -race ./...`、`go vet ./...`
- 后端测试:T-226 至 T-229 已运行 `go test ./...`、`go test -race ./...`、`go vet ./...`
和三个 Go 入口构建;T-227 增加 Go source 的伪 ERP 会话预检、完整单号、日期分页去重、
详情 allowlist 和稳定错误码覆盖;根 `init.ps1` 的 Android 测试/Debug APK 与 Go 标准
验证也通过,均未访问真实 ERP;
@@ -106,7 +107,9 @@
付款、重复提交或自动支付动作。隔离数据库真实 SSR 已通过三个响应式视口验收。
- T-220 至 T-228 ERP 来源:字段契约已固定 stock/detail/item 外部身份、PII 最小化和
缺图边界;Go API 以受锁内存会话完成受控验证码登录,并直接按完整单号或日期范围查询
allowlist schema。旧 Python Connector、8091 端口和共享服务密钥已删除;未访问线上 ERP。
allowlist schema。T-229 仅允许 API 从当前目录 `.env` 回退读取三个 ERP 配置,且不会
改写进程环境或加载其他配置。旧 Python Connector、8091 端口和共享服务密钥已删除;
未访问线上 ERP。
- Workflow:纯 Kotlin runner 已支持步骤 timeout、最多 3 次 retry、安全阻塞、
用户停止和单 runner 并发拒绝;T-102 已接入搜索加有界候选采集五步
- TaskSource:严格 CLI 已生成并验证真实私有 ProbeTask;默认 APK 不含私有 fixture
@@ -183,6 +186,7 @@
| `docs/tasks/T-226.md` | DONE | Go ERP 会话、验证码登录与 Admin 连接页 |
| `docs/tasks/T-227.md` | DONE | Go 直连顺运宝查询接入货运同步 |
| `docs/tasks/T-228.md` | DONE | 移除 Python Connector 并完成 Go 切换 |
| `docs/tasks/T-229.md` | DONE | 从受控 `.env` 加载 ERP 凭证 |
| `docs/design/` | 已确认 | T-202 原型索引、4 个管理页和 7 个 Android 页面 |
| `deepseek总结.txt` | 已有 | 历史讨论摘要,不是正式需求权威 |
| `android-buyer/` | 已有 | Roubao `main` 固定 commit 的 Android 基线 |
@@ -194,12 +198,11 @@
## 任务摘要
- 已完成:T-001 至 T-004、T-101 至 T-104、T-201 至 T-219。
- 已完成:另含 T-220 至 T-228 ERP 契约、货运存储、采购需求生成、日期增量同步、Go
直连协议、人工验证码会话、直连 `FreightSource` 和旧 Connector 清理。
- 已完成:另含 T-220 至 T-229 ERP 契约、货运存储、采购需求生成、日期增量同步、Go
直连协议、人工验证码会话、直连 `FreightSource`、旧 Connector 清理和受控本地凭证加载。
- 进行中:无。
- 下一步:T-229 让本地单机从受控 `backend-api/.env` 读取 ERP 凭证;随后确认开放 API、
数据使用权限,并由人员在 `/erp` 完成验证码登录后以受控单号执行一次不记录订单内容的
smoke。
- 下一步:确认开放 API、数据使用权限,并由人员在 `/erp` 完成验证码登录后以受控单号
执行一次不记录订单内容的 smoke。
## 当前可运行内容
+10 -6
View File
@@ -4,7 +4,7 @@ title: 从受控 .env 加载 ERP 凭证
phase: 2
deps:
- T-228
status: TODO
status: DONE
created: 2026-07-29
context_ref: 13a1355
work_branch: null
@@ -13,6 +13,7 @@ write_paths:
- docs/api.md
- docs/current-state.md
- docs/05-coding-rules.md
- backend-api/.gitignore
- backend-api/.env.example
- backend-api/README.md
- backend-api/SCAFFOLD.md
@@ -44,10 +45,10 @@ T-226 至 T-228 要求 ERP 账号和密码只在后端进程内使用,但当
## 验收要点
- [ ] API 从 `backend-api/.env` 读取完整 ERP 凭证;系统环境变量覆盖同名 `.env` 值。
- [ ] 文件缺失、格式错误、重复键、未知受控键和敏感值均有测试;错误和日志不泄露密码。
- [ ] `.env` 始终被 Git 忽略,`.env.example` 不含真实凭证;Admin 页面仍没有账号/密码字段。
- [ ] `go test ./...`、`go test -race ./...`、`go vet ./...` 和 API 构建通过。
- [x] API 从 `backend-api/.env` 读取完整 ERP 凭证;系统环境变量覆盖同名 `.env` 值。
- [x] 文件缺失、格式错误、重复键、未知受控键和敏感值均有测试;错误和日志不泄露密码。
- [x] `.env` 始终被 Git 忽略,`.env.example` 不含真实凭证;Admin 页面仍没有账号/密码字段。
- [x] `go test ./...`、`go test -race ./...`、`go vet ./...` 和 API 构建通过。
## 边界
@@ -57,4 +58,7 @@ T-226 至 T-228 要求 ERP 账号和密码只在后端进程内使用,但当
## 执行记录
- 2026-07-29:创建任务,等待文档提交后实现。
- 2026-07-29:创建任务并以提交 `d75a7d8` 固定范围。
- 2026-07-29:实现仅限 `cmd/api` 的受控 `.env` 回退;新增 parser/优先级/敏感错误和 API
入口测试。验证:`GOTOOLCHAIN=local go test ./...`、`go test -race ./...`、`go vet ./...`
及三个 Go 入口构建通过;未访问真实 ERP。