chore: harden production readiness gates and runbooks
This commit is contained in:
188
docs/plans/2026-02-09.md
Normal file
188
docs/plans/2026-02-09.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# Implementation Plan: 生产级部署能力 P0 补齐(两周)
|
||||
|
||||
**Branch**: `[prod-p0-hardening]` | **Date**: 2026-02-09 | **Spec**: 当前会话需求(生产部署能力评估后的整改计划)
|
||||
**Input**: 基于当前评估结果(12/24,50%)制定 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: Go(Fiber + GORM-Gen)
|
||||
- Frontend: Vue 3 + Vite(portal/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 application(frontend + 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 增加最小 smoke(API + 页面流)门禁。
|
||||
- [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:密钥轮换影响现网可用性**
|
||||
- 缓解:采用双窗口/灰度切换,先验证再失效旧密钥。
|
||||
|
||||
- **风险2:readiness 判定过严导致误摘流量**
|
||||
- 缓解:设置超时、重试和降级策略,先在预发压测验证。
|
||||
|
||||
- **风险3:CI 门禁增加导致发布节奏变慢**
|
||||
- 缓解:门禁并行化、缓存依赖、区分必选与补充检查。
|
||||
|
||||
- **风险4:演练环境与生产不一致导致“伪通过”**
|
||||
- 缓解:预发配置尽量贴近生产,并记录偏差项。
|
||||
|
||||
## Complexity Tracking
|
||||
|
||||
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
||||
|-----------|------------|-------------------------------------|
|
||||
| N/A | N/A | N/A |
|
||||
Reference in New Issue
Block a user