Files
qinglong/docs/adr/ADR-0361-durable-postgresql-ha-evidence-publication.md
T

61 lines
3.9 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.
# ADR-0361PostgreSQL HA 证据的私有持久发布与离线审计
- 状态:Accepted
- 日期:2026-08-11
- 关联:QL-RFC-0001 D-123、D-273、ADR-0125、ADR-0356
## 上下文
`qinglong/postgresql-ha-contract@v1` 已经能在真实 PostgreSQL 18 Docker 拓扑中证明物理流复制、
`remote_apply`、复制链分区、旧主 fencing、timeline promotion、`pg_rewind` 只读重入、两套 Control
摘流/重建,以及多个领域的 COMMIT-response-loss 收敛。此前脚本只把完整 JSON 写到 stdout;当前报告
约 67 KiB、112 个 gate,终端或 CI 日志截断后无法作为稳定、可离线复核的证据。stdout 成功退出只能
证明当次进程没有抛错,不能证明后来读取的报告与当次运行是同一内容。
## 决策
1. HA contract 在启动 Docker 之前先解析报告目标。调用方可以通过唯一的绝对
`--report=/path/report.json``QL3_HA_REPORT` 指定路径;两者同时出现、路径非规范、父目录为
symlink/非 canonical 或目标已存在时失败关闭。未指定时只为本机交互运行选择一个随机私有临时路径。
2. 完整报告以同目录随机 `0600` 临时文件写入并 fsync,随后以 hard-link no-replace 原子发布,再 fsync
父目录;无论成功或失败均删除临时文件。脚本不覆盖已有证据,也不使用跨文件系统 rename、shell
重定向或可预测临时名。
3. stdout 只保留单行低敏 envelope:fixture、状态、报告绝对路径、完整序列化 SHA-256、架构、PostgreSQL
version number、promotion 前后 timeline 和 gate 数。完整领域记录不再挤入 CI 日志。
4. 独立 `ql3-postgres-ha-evidence-audit` 只读接受 canonical、当前 UID/root 拥有、精确 `0600`、不超过
4 MiB 的普通文件。它复核 PostgreSQL 18、x64/arm64、物理 streaming/`remote_apply`、同步 standby、
timeline 单调提升、旧 control 摘流、新 control 重建、分区写不被确认、promotion guard、`pg_rewind`
只读同步重入、ambiguous/uncommitted transaction 窗口、至少 100 个且全部为 true 的 gate、关键 timeline
顺序、固定 limitation 和已知测试 credential/material 字符串不存在。
5. 默认双架构 HA CI 必须为每个 matrix runner 创建私有报告目录,运行 contract 后立即运行独立 auditor
并以包含 architecture/run ID/attempt 的名称保存 14 天 artifact。workflow run metadata 提供 commit/run
归属;本机 dirty-worktree 报告不得冒充 release provenance。
## 不采用方案
- **继续依赖 stdout 日志**:大报告会被截断,不能 no-replace,也不能离线复核文件身份。
- **直接覆盖固定报告路径**:重跑会抹掉旧事实,无法区分新旧拓扑结果。
- **只检查 `gates.passed`**:单个总布尔值不能发现 gate 集合缩小、timeline 倒序、limitation 漂移或私有材料泄漏。
- **把 Docker HA 称为生产 STONITH/代理证据**:现有 test-only endpoint 和 promotion guard 的限制保持不变;
CloudNativePG/基础设施 fencing 仍由独立门负责。
## 结果
2026-08-11 在 arm64 重新运行修改后的完整门禁,退出码为 0。报告为 67,585 bytes、mode `0600`
SHA-256 `4793bb15bf3fa680a7a5d8873d0d4e58604e944fc7207d38a50470f83beaa0a4`stdout envelope
记录 PostgreSQL 18.4 (`180004`)、timeline `1 → 2` 和 112 个 gate。独立 auditor 返回
`compatible=true``findings=[]`,临时 `ql3-ha-*` 容器零残留。
该变更不修改 migration、数据库角色、HA 故障注入、生产 Pool、Profile closure 或任何常驻进程;只是把
已有真实门的输出从易失日志升级为可保存、不可覆盖、可离线审计的证据。
## 验证
```bash
install -d -m 0700 /absolute/private/ql3-postgres-ha
QL3_HA_REPORT=/absolute/private/ql3-postgres-ha/report.json \
pnpm test:postgres-ha:ql3
pnpm audit:postgres-ha-evidence:ql3 -- \
--report=/absolute/private/ql3-postgres-ha/report.json
```