Files
cmroubao/docs/tasks/T-201.md
T

127 lines
6.5 KiB
Markdown
Raw Normal View History

---
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。