Files
fire-safety-ymd/docs/project/backend-development-guidelines.md
2026-09-05 15:46:37 +08:00

142 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# fire-safety-ymd Go 后端开发规范
## 1. 当前技术基线
| 项 | 当前选择 | 说明 |
| --- | --- | --- |
| Go module | `fire-safety-ymd` | 临时名称,正式仓库路径待确认 |
| Go 工具链 | 本地 `1.26.6`;Docker builder `1.26.8` | 本地测试已验证;镜像版本已显式固定,目标服务器构建待验证 |
| HTTP | 标准库 `net/http` | 当前无需 Web 框架 |
| 测试 | `testing`、`httptest` | 当前无第三方测试库 |
| 数据库 | PostgreSQL + PostGIS + `pgx/v5 v5.10.0` | 原生 pgxpool、固定只读 SQL;实库 SRID 严格 readiness 已通过 |
| AI 集成 | SuperAgent Open API Adapter + MCP `2025-06-18` | 协议代码已实现并默认关闭;真实环境待联调 |
引入依赖前优先核对官方版本、Go 版本要求、维护状态、许可证和可替代性。核心依赖升级需要独立验证,不能只修改版本号。
## 2. 目录职责和依赖方向
```text
cmd/server 进程入口、信号处理、依赖装配
internal/app 应用生命周期与顶层 wiring
internal/config 配置读取、默认值和校验
internal/handler HTTP/MCP 入站契约和响应映射
internal/service 用例编排、授权后的业务流程
internal/domain 稳定领域概念、值对象和业务规则
internal/repository PostgreSQL/PostGIS 等持久化适配
internal/integration SuperAgent 等外部系统协议适配
pkg 真正需要对外复用的稳定包
```
依赖原则:
- `cmd/server` 只装配,不承载业务逻辑。
- Handler 不直接执行 SQL,不直接依赖 SuperAgent 厂商 DTO。
- Service 通过小接口使用持久化或外部系统;接口优先定义在使用方附近。
- Domain 不依赖 HTTP、数据库驱动、MCP SDK 或 SuperAgent SDK。
- Repository 负责参数化查询、行映射和数据库错误转换,不组织自然语言回答。
- 避免为了分层而创建一一映射的空结构;只有出现真实职责时才增加文件和抽象。
## 3. 包与 API 设计
- 包名短、小写、表达单一能力,不使用 `utils`、`common`、`base` 等无边界集合。
- 导出标识符必须有稳定的外部使用场景;默认保持在 `internal` 或不导出。
- 接口应小,由调用方定义;不要先为每个结构体创建接口。
- 构造函数显式传入必需依赖,依赖缺失应尽早失败。
- 避免包级可变状态、隐式 `init` 副作用和 service locator。
- `context.Context` 作为有取消、超时或请求范围操作的第一个参数,不保存在长期结构体字段中。
- 时间使用 `time.Time`/`time.Duration`;跨系统时间格式、时区和精度必须在契约中明确。
## 4. 错误处理
- 正常业务失败返回错误,不使用 `panic`。
- 使用 `fmt.Errorf("动作和对象: %w", err)` 添加上下文并保留错误链。
- 用 `errors.Is`/`errors.As` 判断语义,不比较错误文本。
- Domain/Service 错误映射为稳定 API code;客户端不依赖中英文 message 做逻辑判断。
- HTTP 响应和日志不回显 SQL、凭证、Token、完整个人信息或第三方原始敏感响应。
- 不静默吞掉影响正确性的错误;确实只能忽略时要有注释或受控观测方式。
## 5. HTTP 规范
- 路由显式声明方法;不支持的方法返回 405。
- JSON 响应设置 `Content-Type: application/json; charset=utf-8`。
- Handler 只做协议解析、格式校验、可信身份上下文读取、调用 Service 和响应映射。
- 请求体设置合理大小上限;服务端设置 Header、请求、空闲和优雅关闭超时。
- 后续统一错误格式、请求 ID 和日志关联字段,并在 Spec/OpenAPI 中形成唯一契约来源。
- `/health` 当前是 liveness,只说明进程可处理 HTTP;依赖就绪检查应使用独立 readiness 端点,不能改变现有语义而不更新契约。
## 6. 配置与 Secret
- 环境变量名称使用项目明确前缀,例如 `FIRE_SAFETY_`。
- 配置由 `internal/config` 一次读取、校验并作为不可变值注入。
- Secret 不设置可误用的生产默认值,不写入仓库、命令参数、普通日志或错误响应。
- 本地 `.env` 被忽略;需要示例时只提交无真实值且有注释的 `.env.example`。
- 启动时验证必需配置,错误指出配置键但不输出其值。
## 7. PostgreSQL/PostGIS 规范
数据库接入遵守:
- 当前使用 `pgx/v5` 原生 `pgxpool`;升级前核对 Go/PostgreSQL 支持范围、安全变更和回归测试。
- 所有值使用参数绑定,表名和排序字段使用代码白名单;绝不拼接模型生成 SQL。
- 使用最小权限数据库角色,MCP 第一阶段默认为只读。
- 查询设置请求超时和数据库 statement timeout;分页、数量上限和空间半径必须有限制。
- 事务边界由 Service 用例决定,Repository 不隐藏跨用例事务。
- 已发布 migration 只追加,不原地篡改;导入原始 SQL 前单独审计 `DROP`、sequence、owner 和 extension 依赖。
- `geometry` 的 SRID、实际类型和有效性先通过真实数据核验,再决定字段约束与查询。
- 经纬度距离计算明确选择合适的 `geography`、投影转换或测地算法,并以米等业务单位返回。
- 用 `ST_DWithin` 等可利用 GiST 索引的条件限制候选集,避免对整表逐行计算距离。
- WKB、GeoJSON、经纬度和 MultiLineString/Polygon 映射必须有代表性测试。
## 8. SuperAgent 与 MCP 适配
- 外部 SDK 和 DTO 只存在于适配层;Service 使用项目自己的端口和领域对象。
- 当前 SuperAgent Adapter 分离 `CreateSession` 与 `StreamMessage`;上层负责持久化本地会话映射,不能每轮隐式创建新 Session。
- SSE 成功必须同时具备最终内容、成功 `run.completed` 和顶层 `end`;断流只恢复既有 Run,不重新 POST 消息。
- DashScope 风格兼容 Handler 只做入站协议转换,与原生 `/api/chat` 共享 Chat Service;兼容 `session_id` 必须映射本地会话,不能直接暴露或接受 Provider Session。
- 兼容 SSE v1 不透传 `message.delta`;只有严格成功后才以 `finish_reason=stop` 返回正文。若要真正逐字输出,必须先更新 Spec、安全失败语义和客户端验收条件。
- 当前 MCP 只实现 `2025-06-18` 的 initialize、initialized notification、tools/list、tools/call 和同步 JSON 响应;扩展 SSE、session 或新协议版本前需更新 Spec。
- 重试只用于可安全重试的操作,并设置次数、退避和总时限;避免重复创建会话或重复业务动作。
- MCP 工具按领域能力命名,输入输出 schema 稳定、有限且有中文业务说明。
- `user_id`、角色、租户/区域等授权上下文由服务端注入,不成为模型可自由选择的普通参数。
- 工具结果保留结构化状态、来源和不确定性,不让 Agent 解析日志或数据库原始字段。
## 9. 测试与验证
基础命令:
```bash
gofmt -w ./cmd ./internal
go test ./...
```
按风险增加:
```bash
go vet ./...
go test -race ./...
```
测试要求:
- 纯逻辑优先使用表驱动单元测试。
- HTTP 使用 `httptest` 验证方法、状态码、Header、JSON 和错误边界。
- Repository 集成测试使用隔离数据库和可重复迁移,不依赖个人长期数据库。
- PostGIS 测试覆盖 SRID、点/线/面、边界点、空几何、无效几何、半径上限和排序稳定性。
- 外部适配测试覆盖超时、取消、断流、限流、鉴权失败和不完整事件。
- 测试夹具不得包含真实联系人、Token、生产坐标或客户数据。
## 10. 日志与可观测性
- 使用结构化日志字段表达 request、tool、duration、result 和 error category,避免拼接大段原始内容。
- 不记录 Authorization、Cookie、数据库 DSN、完整用户问题中的敏感信息或完整 MCP 结果。
- 后续为 HTTP、SuperAgent、MCP 和数据库调用建立统一 request/correlation ID。
- 指标区分业务无结果、权限拒绝、上游失败、超时和内部错误,不能只看 HTTP 500 总数。
## 11. 提交前检查
- 仅包含本 checkpoint 文件,没有覆盖用户已有变更。
- `gofmt` 和相关测试已运行。
- 新依赖有理由且 `go.mod`/`go.sum` 一致。
- 没有 Secret、真实敏感数据、构建产物或 IDE 文件。
- Project State、接口、安全和相关设计文档已同步。