57 lines
3.9 KiB
Markdown
57 lines
3.9 KiB
Markdown
---
|
||
feature: reliability-security-fixes
|
||
status: delivered
|
||
specs:
|
||
- docs/compose/specs/reliability-security-fixes.md
|
||
- docs/compose/specs/2026-07-09-clickhouse-migration.md
|
||
plans:
|
||
- docs/compose/plans/reliability-security-fixes.md
|
||
- docs/compose/plans/2026-07-09-clickhouse-migration.md
|
||
branch: main
|
||
---
|
||
|
||
# 可靠性与安全修复 - 最终报告
|
||
|
||
## What Was Built
|
||
|
||
本轮完成了 token_thief 的可靠性与安全加固。异步日志队列现在安全处理并发 `Submit`/`Stop`、使用条目数和字节双预算、在统一 shutdown deadline 内排空,并区分 ClickHouse 的可安全重试、确定失败和提交结果不明三类写入结果。
|
||
|
||
反向代理现在对请求体读取、上游响应复制、普通响应超时、SSE idle timeout、WebSocket 101 元数据和升级连接关闭实施完整性保护。客户端错误文本不再泄露内部信息,转发来源头仅在直接对端属于 `TRUSTED_PROXIES` 时参与客户端 IP 判定。
|
||
|
||
配置、ClickHouse DSN/TLS、数据库 schema 和 Compose 部署均采用 fail-closed 校验与更安全默认;服务启动错误和信号关闭共用资源清理路径。
|
||
|
||
## Architecture
|
||
|
||
`config/config.go` 在启动前严格解析正值预算、duration、布尔值、可信代理和 DSN。`proxy/` 在转发前完整读取请求体,通过 capture writer 和 response body wrapper 判断响应是否完整,并管理 hijacked 连接。`logger/queue.go` 提供非阻塞有界队列,按 `PrepareBatch`、`Append`、`Send` 阶段决定重试或丢弃;`db/` 只在连接、迁移和 schema 校验均成功后标记健康。`main.go` 用一个 30 秒 shutdown context 依次关闭 HTTP、升级连接、队列和数据库。
|
||
|
||
### Design Decisions
|
||
|
||
- 选择仅重试 `PrepareBatch` 失败,因为此时可确定没有提交;`Send` 失败计为 ambiguous 且不重放,避免静默重复。
|
||
- 选择进程内有界 best-effort 队列,因为当前项目没有持久化 outbox;该策略明确不承诺跨进程 exactly-once。
|
||
- 选择 WebSocket 仅记录 101 握手元数据并管理连接,不采集帧,以保持代理边界和关闭行为可测试。
|
||
- 选择拒绝不兼容 ClickHouse schema,而不是自动破坏性迁移或重建表。
|
||
|
||
## Usage
|
||
|
||
必须设置 `UPSTREAM_URL`、`CLICKHOUSE_URL`,Compose 部署还必须显式设置强 `CLICKHOUSE_PASSWORD`。关键新增配置包括 `LOG_QUEUE_BYTES`、`UPSTREAM_RESPONSE_TIMEOUT`、`UPSTREAM_STREAM_IDLE_TIMEOUT` 和 `TRUSTED_PROXIES`;所有预算和 timeout 必须大于零。`CLICKHOUSE_URL` 支持严格的 `host:port`、`clickhouse://` 和 `clickhouses://`,TLS 与压缩参数受白名单校验。
|
||
|
||
## Verification
|
||
|
||
最终验收从工作区根目录运行 `gofmt -l .`、`go test -count=1 ./...`、`go vet ./...` 和 `go build ./`。报告保留可复现命令而不固化会随测试增删失真的测试或包计数;针对 config、queue、ClickHouse、HTTP/SSE/WebSocket 和 Compose 的失败路径均有测试覆盖。
|
||
|
||
## Journey Log
|
||
|
||
> Brief notes on what informed the final design. Not required reading.
|
||
|
||
- [lesson] 迭代 1:网络写入的 `Send` 错误无法证明提交与否;最小安全策略是不自动重试、显式统计 ambiguous,并将连接标记为不健康。
|
||
- [lesson] 迭代 1:进程内队列只能提供有界 best-effort;跨进程幂等需要持久化 outbox 和下游幂等协议,不能由本地重试可靠模拟。
|
||
- [pivot] 迭代 1:SSE 完成判定限定为真正的 `text/event-stream` 且等待代理正常返回,避免终止标记导致提前记录不完整响应。
|
||
- [lesson] 迭代 4:最终报告记录禁用测试缓存的验证命令而非易过期的精确计数,并同时执行格式、静态检查和构建。
|
||
|
||
## Source Materials
|
||
|
||
| File | Role | Notes |
|
||
|------|------|-------|
|
||
| `docs/compose/specs/2026-07-09-clickhouse-migration.md` | 安全修复规格 | 定义本轮行为边界与取舍 |
|
||
| `docs/compose/plans/2026-07-09-clickhouse-migration.md` | 实施计划 | 覆盖跨模块修复和验证 |
|