--- id: T-201 title: 生成并收敛 Go-Gin、SQLite 和迁移骨架 phase: 2 deps: - T-104 status: DONE created: 2026-07-25 context_ref: 84f2da3cf74a17c9a1909faf668f16f5fc4e5afa work_branch: main write_paths: - backend-api/** - init.ps1 - init.sh - README.md - docs/00-ai-start-here.md - docs/03-tech-stack.md - docs/04-architecture.md - docs/05-coding-rules.md - docs/api.md - docs/current-state.md - docs/tasks/T-201.md - progress.md --- ## 问题 / 背景 Phase 1 已证明 Android 能从私有任务完成结构化需求提取、拼多多有界搜索、最多 5 个 候选评估并停在人工确认点。Phase 2 需要统一后端承载后续的管理 Web、手动领取、租约 和结果回传,但仓库当前没有 Go module、HTTP 服务、SQLite 生命周期或迁移入口。 ## 关联需求与交互 - 功能:F-001、F-002、F-003、F-007 的共享后端基础,不在本任务实现业务接口。 - 用户故事:US-001、US-002、US-003、US-007 的前置基础设施。 - 交互:不适用;T-202 才生成并确认 P0 Web/App 原型。 - 架构/API:`docs/03-tech-stack.md` 后端版本与骨架选择、`docs/04-architecture.md` Backend API 分层、`docs/api.md` 通用 HTTP 约定。 ## 方案 1. 固定 Go Blueprint v0.10.11,在仓库外临时目录生成最小 Gin + SQLite 项目作为 一次性参考,不直接保留演示业务和生成器默认配置。 2. 建立 `cmd/api` 和 `cmd/migrate` 两个入口;应用入口只负责装配、信号处理和优雅 关闭,迁移入口显式执行版本化 SQL。 3. 使用 Go 1.23.0、Gin 1.11.0、`database/sql`、`mattn/go-sqlite3` 和 Goose v3.26.0;所有验证设置 `GOTOOLCHAIN=local`。 4. 配置、SQLite、迁移和 Gin transport 分包;关闭默认 CORS,不读取或提交 `.env`, 默认只监听本机回环地址,健康检查失败不得终止进程或泄露内部错误。 5. SQLite 创建父目录、启用 foreign keys、busy timeout 和 WAL,限制单进程写连接, 并由调用方显式关闭数据库。 6. 单元/集成测试覆盖配置边界、健康检查成功/失败、SQLite pragma、迁移 up/down 和 HTTP 路由;根初始化脚本纳入后端测试与构建。 ## 验收要点 - [x] `go.mod` 精确声明 Go 1.23.0、Gin 1.11.0 和固定依赖版本。 - [x] `GOTOOLCHAIN=local go test ./...` 和 Windows 后端构建通过。 - [x] migration 在临时 SQLite 上可 up/down,运行数据目录被 Git 忽略。 - [x] `/healthz` 正常返回稳定 JSON;数据库不可用时返回 503 且进程不退出。 - [x] HTTP Server 具有读头、读、写、空闲和优雅关闭 timeout。 - [x] 没有包级数据库单例、隐式 `.env`、默认 CORS、演示业务或明文凭证。 - [x] 根 `init.ps1`/`init.sh` 同时验证 Android 和后端。 - [x] 启动 smoke、迁移、测试、构建和敏感信息检查均有可复现证据。 ## 边界 - 不实现任务创建、列表、鉴权、claim、租约、事件或资产 API。 - 不实现管理 Web 页面或 Android HTTP TaskSource。 - 不引入 ORM、SPA、Redis、消息队列、WebSocket、Docker 或自动下单逻辑。 - 不提交 SQLite 数据文件、`.env`、密钥、私有任务或生成器临时目录。 ## 执行记录 ### 2026-07-25:任务开始 - 基于 T-104 提交 `84f2da3` 开始。 - 本机已核实 Go 1.23.0、CGO 开启、GCC 可用,且 Go Blueprint 可执行文件存在。 - 先完成骨架生成审计和依赖版本固定,再写入正式代码。 ### 2026-07-25:骨架审计与实现 - 本机 Go Blueprint 精确版本为 v0.10.11;在仓库外临时目录执行文档生成命令, 文件已完整生成,但 CLI 在非交互 PowerShell 恢复终端时返回错误码。 - 生成树当前解析为 Go 1.25.0、Gin 1.12.0,并含默认 CORS、`.env` autoload、 包级数据库单例、`log.Fatal` 健康检查和 Hello World;正式实现未复制这些行为。 - 正式 `go.mod` 固定 Go 1.23.0、Gin 1.11.0、go-sqlite3 1.14.48 和 Goose 3.26.0; v3.27.x 因要求 Go 1.25 未采用。 - 建立 `cmd/api`、`cmd/migrate`、`internal/config`、SQLite、migration 和 `transport/httpapi`;没有提前创建空的 domain/usecase/repository/web 包。 - SQLite 强制 foreign keys、5 秒 busy timeout、WAL、immediate transaction 和 单连接;Gin 默认只监听回环地址,无 CORS/默认 logger,请求异常只记录通用事件。 - 公共错误固定 `request_id`、`retryable=false` 和空 `details`;优雅关闭超时后强制 关闭 listener 并有界等待,避免数据库关闭后继续接受请求。 ### 2026-07-25:自动化验证 - 执行 `$env:GOTOOLCHAIN="local"; go test -count=1 ./...`:25 个测试通过,0 失败; 配置、SQLite、迁移、健康 200/503、安全 recovery、错误合约、404/405、正常关闭和 超时强制关闭均有覆盖。 - 执行 `go test -race -count=1 ./...`、`go vet ./...`、`gofmt -l`、API/migration Windows 构建,全部通过;二进制使用本地 Go 1.23.0 工具链。 - 根目录 `$env:RUN_START_COMMAND="0"; .\init.ps1` 成功完成 Android `test assembleDebug`、后端 test/vet/gofmt 和双入口构建。 - 默认 Debug APK 的 `assets/probe-fixtures/` 条目为 0;`bin/`、`var/`、数据库、 WAL/SHM、日志和 `.env` 均被 Git 忽略。 ### 2026-07-25:迁移与 HTTP smoke - 独立临时 SQLite 执行 `status -> up -> up -> down -> up -> status`: 状态按 pending/applied 切换,第二次 `up` 返回 `applied=0`。 - API Windows 进程使用动态回环端口启动;`GET /healthz` 返回 `{"status":"ok"}`,Cache-Control 为 no-store,未知路由为 404,POST health 为 405,公共错误合约完整,未返回 CORS header,stdout/stderr 字节数均为 0。 - smoke 结束后精确检查 API 测试进程数量为 0。健康 503 和不终止行为由 Fake DB 集成测试验证;不需要破坏真实运行时数据库来制造故障。 ### 未验证项 - 当前 Windows 的 `bash.exe` 指向未配置发行版的 WSL,`init.sh` 未实际运行;脚本 已与 Windows 入口同步 Go/CGO/test/vet/gofmt/build 逻辑,需在 Linux/WSL 复核。 - `/healthz` 当前只表示进程与数据库连接可用,不检查 migration 是否最新;增加 readiness/migration 门禁应在首个业务表落地前完成。 - 默认数据库路径相对启动工作目录;本地命令必须从 `backend-api/` 运行,部署时应 显式配置绝对 `CMROUBAO_DATABASE_PATH`。 - 本任务没有业务表、鉴权、管理页面或任务 API;分别属于 T-202 至 T-205。