chore: harden production readiness gates and runbooks

This commit is contained in:
2026-02-09 11:27:23 +08:00
parent 05a0d07dbb
commit f1412a371d
15 changed files with 1001 additions and 322 deletions

188
docs/plans/2026-02-09.md Normal file
View File

@@ -0,0 +1,188 @@
# Implementation Plan: 生产级部署能力 P0 补齐(两周)
**Branch**: `[prod-p0-hardening]` | **Date**: 2026-02-09 | **Spec**: 当前会话需求(生产部署能力评估后的整改计划)
**Input**: 基于当前评估结果12/2450%)制定 P0 硬化计划,目标达到可审签上线门槛。
## Summary
本阶段聚焦“可发布但未完全生产就绪”的关键缺口,按 P0 优先级补齐以下 5 项:
1. Secrets 治理:移除/替换仓库中生产明文敏感配置,完成密钥轮换与注入规范。
2. 生产数据库 TLS 强制release 模式下禁止 `sslmode=disable`
3. CI/CD 强门禁:强制 backend `go test ./...`、frontend lint(check-only)+build、最小 smoke 验证。
4. 备份恢复与回滚闭环:形成 runbook 并完成预发演练,沉淀可追溯证据。
5. `/readyz` 深度就绪检查:由“存活探针”升级为“依赖感知探针”。
阶段产出是可审签的 Go/No-Go 结论与证据链;未通过门禁则不得标记生产就绪。
## Technical Context
**Language/Version**:
- Backend: GoFiber + GORM-Gen
- Frontend: Vue 3 + Viteportal/superadmin
**Primary Dependencies**:
- Backend: `backend/providers/http/*`, `backend/providers/postgres/*`, `backend/app/commands/*`
- Frontend: `frontend/portal/package.json`, `frontend/superadmin/package.json`
- CI: `backend/.gitea/workflows/build.yml`
**Storage**:
- PostgreSQL
- Redis若 readiness 纳入依赖探测)
**Testing**:
- Backend: `cd backend && env GOCACHE=$PWD/.gocache GOTMPDIR=$PWD/.gotmp go test ./...`
- Frontend:
- `npm -C frontend/portal run lint`
- `npm -C frontend/portal run build`
- `npm -C frontend/superadmin run lint`
- `npm -C frontend/superadmin run build`
- Frontend 页面流(受影响路径):
- superadmin 登录与关键列表页加载
- portal 登录与关键业务页加载
**Target Platform**:
- Linux server / containerized deployment
**Project Type**:
- Web applicationfrontend + backend
**Performance Goals**:
- readiness 依赖检查在健康场景下响应 p95 <= 200ms不含外部网络抖动
- CI 主门禁总时长可控(目标 <= 20 分钟,按流水线并行优化)
**Constraints**:
- 不手改生成文件(`routes.gen.go`, `docs.go`, `swagger.*`
- 控制器保持薄层bind -> services -> return
- 不使用 `as any` / `@ts-ignore` / `@ts-expect-error`
- Bugfix 最小化,不做无关重构
**Scale/Scope**:
- 覆盖 backend 发布安全基线、CI 门禁、前端构建策略、发布/回滚操作基线
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
- ✅ 满足仓库“先计划后实施”要求:本计划作为当前活动计划。
- ✅ 覆盖测试与前端页面流验收要求frontend-involved 必须含页面流 + backend `go test ./...`)。
- ✅ 变更范围集中于 P0 风险,不引入无关架构调整。
- ✅ 包含任务拆解、依赖、验收标准、风险与证据路径。
## Project Structure
### Documentation (this phase)
```text
docs/
├── plan.md # 当前活动计划(本文件)
├── release-evidence/<date>.md # 执行证据(测试/演练/门禁结果)
└── plans/<date>.md # 阶段通过后归档
```
### Source Code (repository root)
```text
backend/
├── .gitea/workflows/build.yml
├── providers/
│ ├── http/engine.go
│ └── postgres/config.go
├── app/commands/
│ └── http/http.go
└── config*.toml
frontend/
├── portal/package.json
└── superadmin/package.json
```
**Structure Decision**: 在现有目录中做增量硬化;不新增子工程,不改动无关模块。
## Plan Phases
### Phase 1 — Secrets 基线治理D1-D2
- 盘点仓库中敏感配置DB/JWT/Storage/第三方凭据)
- 输出替换与轮换清单(包含责任人与窗口)
- 将生产敏感配置改为安全注入策略(模板化占位)
### Phase 2 — 后端安全与可用性护栏D3-D4
- release 模式强制 DB TLS
- `/readyz` 增加依赖探测DB按实际接入补 Redis/Storage
- 补充依赖异常路径测试
### Phase 3 — CI/CD 门禁与前端可复现性D5-D6
- CI 增加强制 test/lint/build/smoke 门禁
- 前端 lint 分离为 check-only 与 fix-only 模式
- 失败即阻断发布流程
### Phase 4 — 恢复能力与回滚演练D7-D8
- 备份/恢复 runbook
- 回滚 runbook应用版本与数据变更策略
- 在预发环境进行演练并记录证据
### Phase 5 — 总体验证与发布评审D9-D10
- 运行全量门禁
- 完成页面流验证
- 形成 Go/No-Go 决策与归档动作
## Tasks
- [x] T1 建立敏感信息台账(位置、等级、替代方案、责任人)。
- [x] T2 制定并执行密钥轮换计划(含失效旧密钥)。
- [x] T3 清理仓库中的生产明文敏感配置,改为模板/注入方式。
- [x] T4 在 backend 增加 release 模式 DB TLS 强制校验。
- [x] T5 升级 `/readyz` 为依赖感知检查(至少 DB
- [x] T6 增加 readiness 相关测试(依赖正常/异常两类)。
- [x] T7 改造 CI加入 backend `go test ./...` 强门禁。
- [x] T8 改造 CI加入 portal/superadmin lint(check-only)+build 门禁。
- [x] T9 增加最小 smokeAPI + 页面流)门禁。
- [x] T10 前端脚本拆分:`lint`(check-only) 与 `lint:fix`(本地修复)。
- [x] T11 编写 backup/restore runbook。
- [x] T12 编写 rollback runbook含触发条件与回退步骤
- [x] T13 在预发完成一次备份恢复演练并留存证据。
- [x] T14 在预发完成一次回滚演练并留存证据。
- [x] T15 执行 backend 全量测试并记录结果。
- [x] T16 执行双前端 lint/build 并记录结果。
- [x] T17 执行受影响前端页面流验证并记录结果。
- [x] T18 汇总发布门禁清单并形成 Go/No-Go 结论。
- [x] T19 Go 时归档 `docs/plan.md` -> `docs/plans/<date>.md`,并清空活动 `docs/plan.md`
## Dependencies
- T1 -> T2 -> T3先盘点再轮换再清理
- T4 + T5 -> T6代码完成后补测试
- T7 + T8 + T9 依赖 T4/T5/T10门禁规则与代码策略一致
- T11 + T12 -> T13/T14先文档后演练
- T6 + T7 + T8 + T9 + T13 + T14 -> T15/T16/T17 -> T18
- T18(Go) -> T19
## Acceptance Criteria
1. 仓库中不再存在生产明文敏感配置;密钥轮换已完成且有记录。
2. release 模式下若 DB 配置非 TLS服务必须拒绝启动并给出明确错误。
3. `/readyz` 能真实反映依赖健康状态(异常返回非 2xx
4. CI 对 backend test、frontend lint/build、smoke 具备不可绕过门禁。
5. backup/restore 与 rollback 均完成至少一次预发演练并有证据。
6. 前端受影响页面流验证通过backend `go test ./...` 通过。
7. 发布结论明确Go/Conditional Go/No-Go并可追溯到证据文件。
## Risks
- **风险1密钥轮换影响现网可用性**
- 缓解:采用双窗口/灰度切换,先验证再失效旧密钥。
- **风险2readiness 判定过严导致误摘流量**
- 缓解:设置超时、重试和降级策略,先在预发压测验证。
- **风险3CI 门禁增加导致发布节奏变慢**
- 缓解:门禁并行化、缓存依赖、区分必选与补充检查。
- **风险4演练环境与生产不一致导致“伪通过”**
- 缓解:预发配置尽量贴近生产,并记录偏差项。
## Complexity Tracking
| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|
| N/A | N/A | N/A |