feat: add read-only retention inventory

This commit is contained in:
2026-09-19 17:21:01 +08:00
parent 6a251e5843
commit da5874b17a
9 changed files with 184 additions and 3 deletions

View File

@@ -159,4 +159,6 @@ Orbit 数据库事务不能自动包含 接入方的业务事务。SDK 的事务
- 恢复旧备份后,可能已有外部业务效果而平台记录回退。必须停止派发、使恢复前的会话与租约失效,并完成必要对账后再开放执行。
- 数据库故障切换与备份恢复是不同故障模型,分别定义验证和可接受损失范围。
当前可用的[`orbit-admin retention inventory`](api/retention.md)只提供按 UTC 截止时间的数量盘点,不执行归档或删除;保留周期、归档格式和受保护记录核对完成前,不得把盘点结果当作清理授权。
MySQL 持久化建议基线为 `innodb_flush_log_at_trx_commit=1`,启用 binlog 时采用 `sync_binlog=1`。副本故障切换的确认语义、RPO / RTO 仍要由具体高可用方案决定。[MySQL 持久化配置](https://dev.mysql.com/doc/refman/8.4/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit)

View File

@@ -61,7 +61,7 @@ P4/P5定时等待与后续查询轮次的实现及回归记录见[时钟报告](
1. 已补[首批可复现故障工具](reports/phase-6-fault-boundaries.md):A04“派发已提交但消息尚未送达”、W01/W13事务提交结果不明,以及W16最终回执/旧PENDING结果重放/下一轮竞争。每个切点必须有实际数据库或进程证据,不能用响应错误推断事务是否已提交,也不能用普通SIGNAL竞争替代最终查询场景。
2. 已实现[基础运行观测](api/observability.md)及[有界业务状态与事件采样](reports/phase-6-business-observability.md):HTTP/WS、数据库连接池、后台批次、固定状态计数、最近事件类别、终态耗时样本、最早年龄、截断/新鲜度指标和可离线验证的告警规则;独立采集监听默认关闭,固定指标目录拒绝动态标签;发布前只读结构核验由[`orbit-admin verify`](api/operations.md)提供。仍需受理/授权阶段端到端延迟与全局持久吞吐、流程Inbox推进延迟、全局发送队列、多节点聚合及生产采集/通知验证。
3. 已补齐受保护管理环境中的固定凭据操作文件、轮换、撤销、幂等回执和脱敏管理审计;轮换保留授权绑定并要求新令牌重新建立会话,撤销允许在停用范围内执行且不改写历史记录。仍需补齐提交不明故障切点、多节点安全重绑演练、凭据最小权限配置核对和生产密钥托管/审计演练。
4. 实现保留/归档与受保护记录核对,再执行备份恢复、兼容升级和六类容量负载。未确认交付、有效幂等身份、当前/历史执行证据和未终结流程不能被普通清理破坏。生产HA及RPO/RTO继续按实际拓扑验证,不缩减为本机多进程检查。
4. 已补[`orbit-admin retention inventory`](api/retention.md)只读盘点和[阶段报告](reports/phase-6-retention-inventory.md),能区分过期幂等、确定终态、未知效果、未终结流程、已确认/未确认交付、已消费/未消费Inbox、事件和审计规模;它不执行归档或删除。后续仍需评审各类保留周期、归档格式、受保护记录核对,再执行备份恢复、兼容升级和六类容量负载。未确认交付、有效幂等身份、当前/历史执行证据和未终结流程不能被普通清理破坏。生产HA及RPO/RTO继续按实际拓扑验证,不缩减为本机多进程检查。
### P3 功能范围核对

View File

@@ -21,6 +21,7 @@
| 任务 `priority` 与节点领取池 | P3 已实现有界优先级加速、应用/队列轮转 | [优先级与公平派发](priority-and-fairness.md) |
| 凭据校验、初始化、固定操作文件轮换/撤销与回执重放 CLI | P1/P6 已实现;不提供公网管理路由,测试专用提交不明切点已回归 | [鉴权](authentication.md)、[凭据报告](../reports/phase-6-credentials.md) |
| `orbit-admin verify` 发布前结构核验 | 已实现只读迁移、零外键和 000026–000028 固定索引检查 | [运维核验](operations.md) |
| `orbit-admin retention inventory` 保留清单 | 已实现带 UTC 截止时间的只读盘点;不执行归档、删除或权限变更 | [保留清单](retention.md) |
| `/v1/worker/connect` | P2 已实现并通过阶段验收 | [Worker 契约](worker.md)、[Schema](worker-schema.md) |
| 任务相对延迟 `delay_ms` | 已实现数据库计时、原键恢复与实际执行例子 | [任务接口](tasks.md)、[延迟示例](../examples/delayed-task.md) |
| 任务冻结策略与 Worker `retryable` | P3 安全重试已实现 | [安全重试](retries.md) |

19
docs/api/retention.md Normal file
View File

@@ -0,0 +1,19 @@
# 保留清单(只读)
`orbit-admin retention inventory` 用于在制定保留窗口、归档和备份恢复方案前盘点历史数据。它只执行带截止时间的统计查询,不删除、搬迁、改写数据,也不会自动判断某条记录可以安全归档。
```sh
ORBIT_MYSQL_DSN='user:password@tcp(127.0.0.1:3306)/orbit' \
go run ./cmd/orbit-admin retention inventory \
--before 2026-09-18T00:00:00Z
```
示例输出:
```json
{"cutoff":"2026-09-18T00:00:00Z","expired_idempotency":0,"terminal_tasks":0,"uncertain_tasks":0,"active_tasks":0,"terminal_workflows":0,"active_workflows":0,"acknowledged_deliveries":0,"unconfirmed_deliveries":0,"processed_inbox":0,"unprocessed_inbox":0,"events":0,"audit_events":0}
```
所有时间按 UTC 解析,严格早于 `--before` 的记录才计入。截止时间不能晚于数据库当前时间,避免把未来记录误认为历史。`terminal_tasks` 只统计确定终态且 `effect_uncertain=false` 的任务;`uncertain_tasks`、`active_tasks`、`active_workflows`、`unconfirmed_deliveries` 和 `unprocessed_inbox` 是需要先处理或保留的阻塞项。
结果是盘点快照,不是归档授权。真正的清理或归档还必须完成保留周期评审、未确认副作用核对、事件投递和流程推进核对、备份恢复演练、权限隔离及审计;当前命令没有 `apply` 或删除路径。

View File

@@ -0,0 +1,25 @@
# P6:保留清单与归档前置核对
日期:2026-09-19。本批先交付只读盘点,避免在保留周期、备份恢复和外部效果尚未评审时提供危险的自动删除入口。
## 已实现
- [`ReadRetentionInventory`](../../internal/storage/mysql/retention_inventory.go) 接受明确的 UTC 截止时间,只统计严格早于截止时间的记录。
- `orbit-admin retention inventory --before RFC3339` 通过独立管理命令输出 JSON;数据库时间校验会拒绝未来截止时间,数据库连接、查询失败不会泄露 DSN 或 SQL。
- 盘点固定覆盖幂等、确定终态/未知效果/未终结任务、确定终态/未终结流程、已确认/未确认交付、已消费/未消费流程 Inbox、追加事件和管理审计。
- 任何查询只读,不执行 DDL、删除、搬迁、权限修改或幂等重置;CLI 没有 `apply` 参数。未确认交付、未消费 Inbox、未知效果和未终结实体被单独列为阻塞数量。
## 回归证据
- `go test ./cmd/orbit-admin ./internal/storage/mysql` 通过;存储集成用例使用真实 MySQL 验证:明确放到截止时间之前的确定终态任务计入 `terminal_tasks`,未知效果为零,未来截止被拒绝。
- 标准 `DOCKER=... GO=... sh scripts/test-mysql.sh` 在 Go 1.27.1、Docker MySQL 8.4.10 环境退出码为 0。脚本实际输出:
```text
{"cutoff":"2000-01-01T00:00:00Z","expired_idempotency":0,"terminal_tasks":0,"uncertain_tasks":0,"active_tasks":0,"terminal_workflows":0,"active_workflows":0,"acknowledged_deliveries":0,"unconfirmed_deliveries":0,"processed_inbox":0,"unprocessed_inbox":0,"events":0,"audit_events":0}
```
同轮已有迁移、零外键、凭据、Pulse/Weave 真实进程强杀恢复、SDK 和两个独立业务示例均通过。
## 边界与后续
盘点数量不是归档授权,也不证明某类记录可独立删除。正式归档前仍需确定每类保留周期和归档格式,核对事件交付、流程推进、有效幂等身份、未知外部效果、审计保留与备份恢复;还需要隔离环境恢复演练、权限隔离、容量和生产拓扑验证。当前没有自动清理路径,防止把测试环境的历史数量误当成生产策略。