补强生产数据路径与备份来源护栏(07-26-internal-ops-recovery-baseline)
这个提交包含在:
@@ -21,7 +21,7 @@ isolated drill
|
||||
|
||||
- 一个批次只使用一个 `run_id`,由上层入口传递明确的 `OUT_FILE` 给现有底层脚本。
|
||||
- 先把产物写入批次临时目录;DB 和附件均成功并通过完整性检查后,再写 manifest 并把批次标记为完整。
|
||||
- manifest 使用稳定、脱敏的键:`schemaVersion`、`runId`、`createdAt`、`buildSha`(如可安全取得)、两份相对文件名、字节数和 SHA-256。
|
||||
- manifest 使用稳定、脱敏的键:`schemaVersion`、`runId`、`createdAt`、`buildSha`(真实可知时)、`sourceImageDigest`(实测可知时)、两份相对文件名、字节数和 SHA-256;两类来源标识至少有一项。
|
||||
- 不把连接串、容器密码、存储源路径、真实业务文件清单或主机绝对路径写入 manifest。
|
||||
- 本任务不负责异机传输实现;runbook 要求操作者把完整批次复制到异机/异盘,并记录保留周期。
|
||||
|
||||
@@ -121,11 +121,14 @@ GET /auth/wecom/login?mode=onboard
|
||||
- DB 不发布宿主端口;应用仅通过 Compose 内部网络访问 `db`。环境契约必须拒绝 DB `ports`、固定容器名或未参数化数据目录回退。
|
||||
- Docker 备份/恢复必须显式传入由 `compose ... ps -q db` 得到的已核验容器 ID;附件备份必须显式传入活动挂载源,两个脚本都不猜默认值。
|
||||
- 远端 `/ready` 构建标识在 server 容器内用 Node 校验,宿主机只负责 curl 和 Compose,不要求安装 Node。
|
||||
- `deploy.sh` 不解析或 source 远端 `.env` 来猜宿主路径;调用者必须在发布命令中显式传入受限字符集的绝对 `POSTGRES_DATA_DIR`、`STORAGE_HOST_DIR` 和数据模式。`existing` 要求目录已存在且 PGDATA 含 `PG_VERSION`;`initialize` 才允许创建空目标。
|
||||
- 本地直接 Compose 可继续使用示例相对默认值,但正式发布入口拒绝相对路径,从而避免项目名变化时 Docker 以 root 静默创建第二套空目录。
|
||||
- manifest 的 `buildSha` 优先使用调用者显式值,否则仅在本地 Git 工作树存在时推导;另以可选 `sourceImageDigest` 记录活动镜像不可变标识。旧实例 build SHA 不可知时只记录实测 digest,不填写目标提交。
|
||||
|
||||
### 生产统一顺序
|
||||
|
||||
1. 另行获批后,从活动 DB 和活动附件挂载源重新生成成对异机备份作为灾难回滚点;旧批次因混入非活动附件目录只保留审计,并记录活动数据挂载、环境摘要、容器镜像和 Caddy 端口。
|
||||
2. 本地先修复 Compose 可配置回环端口及部署脚本动态端口探测,通过全部门禁并提交、发布批准提交。
|
||||
3. 停机后把非活动的既定部署目录改名保留,将活动数据目录和环境文件迁入既定目录;同一文件系统优先原子改名,不复制运行中的 PostgreSQL 文件。
|
||||
3. 停机后把活动 PGDATA 和附件复制到新的显式绝对目录,复制前目标必须为空;保留旧目录原位且不再挂载写入,直到观察期结束。复制仅在旧 PostgreSQL 完全停止后执行,并保留所有权、权限、链接和扩展属性。
|
||||
4. 用新 Compose 重建 db/init/server,应用已提交 migrations;旧容器和旧目录在验收前保留,不清理。
|
||||
5. 公网构建标识、数据计数、角色、企微入口和关键只读检查通过后更新运维 timer;失败则停止新容器并恢复旧目录/容器和原 Caddy 目标。
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
- [ ] 修复部署脚本的现场端口解析,确定唯一部署目录,并在活动 DB/附件挂载、环境摘要和旧镜像回滚点全部确认后才执行获批切换。
|
||||
- [x] 完成本地 Compose/备份加固:移除固定容器名和 DB 宿主端口,参数化数据目录,deploy/timer 显式 project,备份来源缺失硬失败,远端构建标识改由容器内 Node 核验。
|
||||
- [x] 增加隐式附件源、隐式 DB 容器、DB 端口与固定容器名回退的负向契约演练;未部署或启用新 Compose。
|
||||
- [x] 收紧正式 deploy 数据路径:显式绝对路径、`existing|initialize` 模式、既有 PGDATA 标记和禁止 Docker 静默建空目录。
|
||||
- [x] 让成对 manifest 尊重显式 `BUILD_SHA` 并支持活动镜像 digest;补 Node/Python 等价与非法来源标识负向测试。
|
||||
- [x] 把旧 Compose project 实测、镜像 digest、58 项迁移与关键表计数、影子逐表/附件计数验收、停机后复制并保留旧目录写入 runbook/checklist/spec。
|
||||
- [ ] 部署后验证唯一 Compose 来源、构建标识、迁移状态、Caddy 公网 `/ready` 和前端 marker;不因服务可访问而忽略来源漂移。
|
||||
- [ ] 用户在企微应用详情选择手机、邮箱、企业邮箱敏感字段;部署开关开启后,两名目标分别通过一次性链接本人确认授权。
|
||||
- [ ] 两人自助开通成功后写入获批 `finance` / `ceo` 职责,复核不同身份、maker-checker、会话撤销、审计和付款零写入。
|
||||
@@ -63,6 +66,7 @@
|
||||
- 合成备份恢复在 Node 路径和移除 Node 的 Python 3 回退路径均通过,最近两次本地参考 RTO 均为 6 秒;负向覆盖隐式附件源、隐式 DB 容器、DB 宿主端口、固定容器名和 deploy 缺失 project name。
|
||||
- 本阶段授权仅覆盖本地文件、测试、规约和提交,不包含生产备份、停机、迁移、部署、timer 安装或企微写入。
|
||||
- 已确认旧异机批次混用了活动 DB 与非活动附件目录,保留审计但不再作为活动实例成对恢复证据;正确批次须另行批准重做。
|
||||
- 复核补修后,正式 deploy 的相对/重叠路径负向门禁、显式来源标识、Node 路径以及无 Node/无 Git 的 Python 3 + digest-only 路径均通过;最近两次合成 RTO 均为 7 秒。
|
||||
|
||||
## 回滚点
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
- 普通 `snsapi_base` 登录、已绑定账号登录和现有绑定流程保持兼容,不因资料授权功能改成每次手工确认。
|
||||
- 生产统一以仓库既定部署目录和 Compose 契约为目标,但活动 PostgreSQL 与附件数据是唯一数据事实源;停机切换不得复制运行中的 PostgreSQL 文件、启动第二套空库或覆盖环境变量。
|
||||
- Compose 项目名、容器身份与 DB/附件目录必须在同一次获批停机窗口切换;DB 不发布宿主端口,备份不得猜测容器名或附件目录。
|
||||
- 正式 `deploy.sh` 必须由调用者显式提供绝对 `POSTGRES_DATA_DIR`、`STORAGE_HOST_DIR` 和 `DEPLOY_DATA_MODE=existing|initialize`;既有实例默认只接受包含 `PG_VERSION` 的现存 PGDATA,不得让 Docker 静默创建空目录。
|
||||
- 成对备份必须尊重调用者显式提供的真实来源标识。当前旧实例没有 build SHA 时记录活动镜像不可变 digest,不得用待部署提交冒充备份来源。
|
||||
- 部署健康检查必须从 Compose 解析实际宿主端口,并校验后端 `/ready`、前端 marker 与批准提交一致;应用已提交的 Prisma migrations 但禁止 reset 或改写历史。
|
||||
|
||||
## Acceptance Criteria
|
||||
@@ -62,6 +64,7 @@
|
||||
- [ ] 一次性授权通过 `getuserdetail` 获取成员同意的手机和邮箱,自动创建或补齐 OA 员工与企微绑定;新建账号角色严格等于 `employee`,日志和审计不含票据或完整敏感响应。
|
||||
- [ ] 部署目录、Compose、环境文件、运维 timer 和活动容器来源统一;活动 DB/附件连续,远端 migrations 与批准提交一致,公网 `/ready` 和前端 marker 返回同一短构建标识。
|
||||
- [x] 本地 Compose、部署、timer 和备份合同完成加固并覆盖负向回退;未把本地通过误报为生产切换完成。
|
||||
- [x] 部署入口拒绝隐式/相对数据目录及缺少数据模式,成对 manifest 可记录显式 build SHA 或活动镜像 digest,并有 Node/Python 等价测试。
|
||||
- [ ] 两名目标成员分别完成一次本人授权后,账号唯一、企微绑定不同,再由管理员写入 `employee + finance` 与 `employee + ceo`;maker-checker、会话撤销和角色审计通过。
|
||||
|
||||
## Out of Scope
|
||||
|
||||
@@ -91,3 +91,11 @@
|
||||
- 企微官方文档复核:2022-06-20 后新建的自建应用不再通过 `/user/get` 返回手机、邮箱和企业邮箱;管理员需在应用详情选择敏感字段,成员使用 `snsapi_privateinfo` 手工授权,`/cgi-bin/auth/getuserinfo` 才返回 30 分钟有效的 `user_ticket`,随后 `/cgi-bin/auth/getuserdetail` 可返回成员同意的手机号、邮箱和企业邮箱。
|
||||
- 当前 OA `server/src/routes/wecomAuth.js` 固定使用 `snsapi_base`,只调用 `getuserinfo` 获取 userid,不调用 `getuserdetail`;因此现状是项目尚未接入官方敏感信息授权链路,而不是企微没有该能力。
|
||||
- 两名目标成员的脱敏结果为匹配计数 `[1,1]`、身份不同、均 active、数据库匹配 `[0,0]`、计划动作均为 create;两人均缺 `phone` 与 `email`,因此没有员工、角色、会话、付款或其他业务写入。
|
||||
|
||||
## 2026-07-27 复核后的执行授权边界
|
||||
|
||||
- 外部复核确认提交 `2334203` 的 Compose、端口、容器名、备份来源硬失败和负向契约方向正确,同时发现正式 deploy 仍会创建默认目录、相对默认值缺少生产护栏、非 Git 主机 manifest 无来源标识三项本地缺口。
|
||||
- 已批准在补齐上述缺口后执行:发布批准提交、生产只读冻结、从活动 DB/附件重做异机成对备份、在隔离影子目标恢复并验收。该授权不包含停机、生产数据目录复制、迁移、新 Compose 启动、Caddy/timer 修改、企微写入或角色写入。
|
||||
- 冻结证据必须包含实测旧 Compose project、不可变镜像 ID/digest、成功 migration 数和固定关键表计数;影子恢复必须逐表比对计数、比对附件普通文件数并运行 schema 兼容镜像 `/ready`。
|
||||
- 当前旧实例没有 build SHA,重做备份不得写入待部署提交。manifest 记录活动容器的实测 `sha256:` 镜像 ID;新版本部署后的备份才能记录其真实 build SHA。
|
||||
- 后续停机预案采用“旧 PostgreSQL 完全停止后复制到空新目录,旧目录原位保留且不再写入”,不把原子改名后的唯一数据副本当作回滚点。
|
||||
|
||||
在新工单中引用
屏蔽一个用户