fix: restore reviewable migration evidence
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
# ClickHouse Migration 安全修复规格
|
||||
|
||||
> [!NOTE]
|
||||
> This document may not reflect the current implementation.
|
||||
> See the final report for up-to-date state:
|
||||
> [Final Report](../reports/reliability-security-fixes.md)
|
||||
|
||||
## 修订范围
|
||||
|
||||
本规格是现有 ClickHouse Migration 的增量修订。保留当前单表 `proxy_logs`、内存异步队列、`httputil.ReverseProxy` 和 best-effort 审计模型,不引入 PostgreSQL 兼容层、持久化 outbox 或 WebSocket 帧采集。
|
||||
|
||||
## 行为要求
|
||||
|
||||
### 队列与关闭
|
||||
|
||||
- `Submit` 始终非阻塞;与 `Stop` 并发、停止后提交和重复停止均不得 panic。
|
||||
- 队列由条数和字节双重预算约束。默认 `LOG_QUEUE_SIZE=256`、`LOG_QUEUE_BYTES=67108864`、`MAX_BODY_BYTES=1048576`;任一预算不足即丢弃并计数。
|
||||
- `Stop(ctx)` 使用调用方提供的单一总 deadline 排空;deadline 到期取消所有 worker I/O、丢弃剩余条目并返回错误。
|
||||
- worker flush 后清空 batch 指针并释放条目的字节预留。
|
||||
|
||||
### ClickHouse 写入
|
||||
|
||||
- `PrepareBatch` 错误是确定未提交错误,可有限重试整个 batch。
|
||||
- `Append` 错误是确定未提交错误,必须中止/关闭 batch,并允许逐条隔离坏记录;成功记录继续写入,失败记录明确计数。
|
||||
- `Send` 错误视为提交结果不明,不自动重试或逐条重发,避免静默重复;该批计为 ambiguous drop 并标记连接不健康。
|
||||
- 进程内 best-effort 方案不承诺跨进程 exactly-once。需要更强保证时必须另行引入持久化 outbox 与幂等协议。
|
||||
|
||||
### 代理完整性
|
||||
|
||||
- 请求体预读失败时返回固定 400,不调用 upstream,不转发已损坏请求。
|
||||
- 502 客户端响应只包含固定 `bad gateway` 和 request ID;内部网络错误仅写服务端日志和 `LogEntry.Error`。
|
||||
- 只有 ReverseProxy 正常完成的普通/SSE 响应才提交完整日志。下游写失败、短写、客户端断开或响应复制中断不得提交成完整成功日志。
|
||||
- SSE 终止检测只在响应 `Content-Type` 为 `text/event-stream` 时按完整 event 边界解析。终止事件仅用于状态判断,不触发提前提交;提交仍等待代理正常返回。
|
||||
- 普通 HTTP 响应体使用可配置总 timeout;SSE 使用可配置 idle timeout,成功读取数据后重置;timeout 必须能关闭阻塞中的上游 Body。
|
||||
- WebSocket 成功升级时记录一条 101 握手元数据日志,body 为空。Handler 跟踪已 hijack 连接,并提供受 context 限制的 shutdown 关闭能力;不采集帧。
|
||||
- 默认不信任 `X-Forwarded-For`/`X-Real-IP`。仅当直接对端命中 `TRUSTED_PROXIES` CIDR 时,从 XFF 右向左剥离可信代理并选择最近的不可信地址。
|
||||
|
||||
### 配置与数据库边界
|
||||
|
||||
- 所有整数、布尔值和 duration 环境变量格式错误时启动失败;要求正值的 body、队列、batch、worker、重连和 timeout 配置必须严格大于零。
|
||||
- `CLICKHOUSE_URL` 支持严格 `host:port`、`clickhouse://` 和 `clickhouses://`。仅允许 `secure`、`skip_verify`、`compress` 查询参数;未知参数、冲突 TLS 配置、fragment、空 host/port 均失败。
|
||||
- 建表后校验 `system.columns` 与 `system.tables` 的必需列类型、引擎、分区键和排序键;不兼容 schema 拒绝标记健康,不自动重建或改类型。
|
||||
|
||||
### 启动与部署
|
||||
|
||||
- server 启动错误与 signal 进入同一清理路径;禁止 goroutine 内 `log.Fatalf` 绕过 defer。
|
||||
- shutdown 总预算依次覆盖 HTTP、升级连接、日志队列、DB 和根 context。
|
||||
- Compose 固定 ClickHouse 明确版本,不使用 `latest`;默认不发布 ClickHouse 端口;`CLICKHOUSE_PASSWORD` 必须显式设置,应用 DSN 使用独立 `CLICKHOUSE_URL`,避免弱默认和 URL 编码冲突。
|
||||
|
||||
## 验证
|
||||
|
||||
- 针对上述失败路径增加 config、logger、proxy、db 单元测试。
|
||||
- 运行 `gofmt`、`go test ./...` 和 `go vet ./...`。
|
||||
- 使用 Git 提交保留完整变更证据;审查应以提交及其 diff 验证实现和验收项。
|
||||
Reference in New Issue
Block a user