Files
orbit/docs/07-data-model.md

269 lines
30 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.
# 数据模型与实现基线
更新:2026-09-22。数据库统一禁止外键。当前迁移版本为30;000026–000028只增加固定业务观测读取所需索引,000029增加控制台账号/会话,000030增加命名空间级保留策略。当前已实现任务执行、安全重试、运行中取消、计划调度、队列限速/背压和应用配额;优先级及节点公平领取已实现;可靠订阅核心、HTTP/WSS、管理与消费 SDK 已实现,独立 Inbox 场景已实现,流程编排继续开发。
## 1. 模块与依赖
- `model/`:ID、摘要、JSON、命名空间记录等公共原语。
- `platform/model/`:应用、命名空间、凭据、幂等、事件、订阅交付及审计。
- `pulse/model/`:队列、执行门控、进程/会话、任务、尝试、回执、迟到证据、并发许可和调度计划。
- `weave/model/`:定义及不可变版本、实例、步骤激活、等待、信号、查询轮次与恢复记录。
- `internal/storage/mysql/`:连接、事务与显式迁移,不向 SDK 暴露。
- `sdk/go/`:独立 Go module;对外 DTO 与服务端模型分别维护。
模型使用普通 Go struct 与 `db` 标签,模型与持久化字段提供中文注释,SQL 表和字段同步维护中文 COMMENT。`TestFreshInstallBaselineHasChineseModelComments` 会在测试门禁中逐表、逐字段检查当前基线,防止新增持久化字段漏写说明。SQL 是可审查的版本化迁移。目前未引入 ORM,也没有自动同步表结构。
## 2. 存储约定
| 项目 | 当前实现 |
| --- | --- |
| 数据库基线 | MySQL 8.4+,本轮在 8.4.10 验证 |
| Go 工具链 | Go 1.27.1;服务端和 SDK 分别编译测试 |
| 标识 | 128 位加密随机 ID;数据库 `BINARY(16)`,对外 32 位小写十六进制字符串 |
| 摘要 | SHA-256,数据库 `BINARY(32)`;执行令牌及凭据原文不进入模型 |
| 租户隔离 | 运行实体以 `(namespace_id, id)` 为主键;资源存在性、命名空间及父资源归属由服务端事务校验 |
| 外键 | 禁止数据库外键;保留关联字段、查询索引、唯一约束和 CHECK |
| 时间 | `DATETIME(6)`,数据库会话与驱动统一 UTC;运行授权依赖数据库时间 |
| 状态 | Go 类型常量 + SQL `CHECK`;状态版本独立于时间戳 |
| CAS | `revision` 从 1 开始;服务层必须带期望版本条件更新并检查受影响行数 |
| 暂停 | 实例执行状态与 `paused` 分开,控制版本与通用门控同事务协调 |
| 参数 | 版本化 JSON 文档或业务侧引用;业务内容使用 MEDIUMTEXT + JSON_VALID 保留数字精度,平台元数据使用原生 JSON |
| 删除 | 禁止级联删除;当前无公开硬删除接口,历史保留。后续清理须由服务端核验引用及保留窗口 |
| 不可变历史 | 流程版本、计划版本、状态事件、审计事件的 `UPDATE` 被数据库触发器拒绝 |
随机 ID 的索引成本需要后续容量测试,不将该选择描述为已经验证的大规模吞吐保证。运行账户应最小授权,迁移与保留清理使用不同身份;触发器不是对数据库管理员的防篡改保证。
## 3. 实体清单
当前共 39 个业务实体:原运行模型为36个,000029增加控制台账号与会话,000030增加保留策略。迁移自身另有 `orbit_schema_migrations` 记录;控制台和策略表同样遵循零外键、中文 COMMENT、应用层归属校验。
| 模块 | Go 模型 | 数据表 |
| --- | --- | --- |
| platform | `Application` | `orbit_applications` |
| platform | `ApplicationResources` | `orbit_application_resources` |
| platform | `Namespace` | `orbit_namespaces` |
| platform | `Credential` | `orbit_credentials` |
| platform | `IdempotencyKey` | `orbit_idempotency_keys` |
| platform | `Event` | `orbit_events` |
| platform | `EventStream` | `orbit_event_streams` |
| platform | `ResultEvent` | `orbit_result_events` |
| platform | `Subscription` | `orbit_subscriptions` |
| platform | `Delivery` | `orbit_deliveries` |
| platform | `AuditEvent` | `orbit_audit_events` |
| platform | `ConsoleUser` | `orbit_console_users` |
| platform | `ConsoleSession` | `orbit_console_sessions` |
| internal/retention | `Policy` | `orbit_retention_policies` |
| pulse | `Queue` | `pulse_queues` |
| pulse | `ExecutionGate` | `pulse_execution_gates` |
| pulse | `WorkerSession` | `pulse_worker_sessions` |
| pulse | `WorkerInstance` | `pulse_worker_instances` |
| pulse | `Task` | `pulse_tasks` |
| pulse | `Attempt` | `pulse_attempts` |
| pulse | `AttemptReceipt` | `pulse_attempt_receipts` |
| pulse | `AttemptEvidence` | `pulse_attempt_evidence` |
| pulse | `ConcurrencyLimit` | `pulse_concurrency_limits` |
| pulse | `Permit` | `pulse_permits` |
| pulse | `Schedule` | `pulse_schedules` |
| pulse | `ScheduleVersion` | `pulse_schedule_versions` |
| pulse | `Occurrence` | `pulse_schedule_occurrences` |
| weave | `Definition` | `weave_definitions` |
| weave | `DefinitionVersion` | `weave_definition_versions` |
| weave | `VersionScope` | `weave_version_scopes` |
| weave | `Instance` | `weave_instances` |
| weave | `Step` | `weave_steps` |
| weave | `Activation` | `weave_activations` |
| weave | `Wait` | `weave_waits` |
| weave | `Signal` | `weave_signals` |
| weave | `PollState` | `weave_poll_states` |
| weave | `PollRound` | `weave_poll_rounds` |
| weave | `InboxEvent` | `weave_inbox` |
| weave | `PendingAdvance` | `weave_pending_advances` |
`orbit_events` 保存原始状态事件,`orbit_result_events` 使用相同事件 ID 保存队列、提交序号和冻结快照,`orbit_event_streams` 串行分配命名空间内的结果序号;对外投递使用 `orbit_deliveries`,内部流程结果原子写入 `weave_inbox`及其独立冻结快照,已接入[实例消费推进](12-workflow-runtime.md)。`weave_pending_advances` 保存根步骤续接和TIMER/SIGNAL/POLL时钟检查点。
## 4. 已落实的数据库约束
- 幂等身份在命名空间、操作和资源作用域内唯一;保存请求摘要和原响应。
- 一个任务的执行代次唯一;当前尝试归属由执行事务另行校验。
- 计划触发按计划与 UTC 原触发时间唯一,计划修改不会绕过触发去重。
- 定义版本不可覆盖;实例保存版本 ID,版本归属校验随流程引擎实现。
- 步骤和激活保留父资源 ID 及关联索引,数据库不校验跨表归属。
- 查询轮次与任务分别唯一;轮次、单轮尝试预算和截止时间独立保存。
- 内部事件与外部订阅交付有去重键,租用状态要求有效租用字段。
- 终态必须有结束时间,待执行任务不能伪造有效执行租约。
- effect_uncertain=true 不能和成功、失败、取消终态共存;尝试/证据 retryable=true 只允许明确失败。
## 5. 服务层关联与事务规则
数据库禁止外键,关联一致性由应用负责;CHECK 仅保证单行约束。任务提交、计划创建和 Worker 注册在同一事务中按 namespace_id 校验队列存在性,校验失败回滚所有新增记录。鉴权校验凭据、命名空间及所属应用;执行入口核验进程、会话、执行代次、任务和尝试归属。接口不能仅相信调用方传入的资源 ID。
禁止“先查后另开事务写入”。需要防止并发状态改变的关联行在事务内持锁,统一锁顺序并保留必要索引。当前不提供硬删除;将来增加清理时,必须核验在途任务、引用、幂等恢复窗口与审计保留期,按有限批次处理,不能依赖数据库级联。直接绕过服务写 SQL 不受应用校验保护。
P1 已完成动作/队列授权、幂等摘要与原回执、受理事件及取消 CAS/审计事务;P3 扩展到运行中取消。订阅已实现服务层及持久化核心,包含事务内队列、所有者和交付归属校验;HTTP/WSS、管理与消费 SDK 已接入,业务 Inbox 示例已独立交付。流程目前仍只具备模型,后续引擎也必须补齐事务内父资源归属验证。
P2 服务端已新增会话隔离、两步派发、租约、并发许可、结果回执/证据和恢复扫描,见 [执行协议](api/worker.md)。底层及自动 Worker SDK、尝试/证据查询、Schema 与进程故障恢复已通过 [P2 阶段验收](reports/phase-2.md)。
1. 权限验证、凭据校验、命名空间过滤和队列消费授权。
2. 同一次事务更新任务、尝试、租约、并发许可、事件与流程交付记录。
3. CAS 竞争、数据库时间校验、门控与开始授权串行化。
4. 对幂等重复请求比较语义摘要,返回原响应或冲突。
5. 计划当前版本与版本内容原子发布,信号匹配正确的业务操作。
6. 查询轮次、预算、下一任务创建同事务提交;未知结果按证据核查。
7. 不可变版本发布前的流程图校验、表达式类型与结构化汇合验证。
局部模型方法不能被当作已经实现了 Worker 执行授权和业务效果幂等。P1 已实现范围与剩余边界见 [P1 报告](reports/phase-1.md)。
## 6. 迁移与回归
入口是 `orbit-migrate up|status`。应用启动及 readiness 检查迁移状态和 Orbit 表的外键数量,发现外键会拒绝启动/就绪,不执行 DDL。这不是全部手工结构漂移审计。迁移持有数据库级命名锁,逐语句应用;失败保留 dirty 标记。由于 MySQL DDL 不整体回滚,修复必须先对照语句和实际表结构完成核查,不提供自动清除 dirty 的命令。
已应用的迁移不得修改。后续使用新的前向迁移;回归环境使用独立临时数据库。初始迁移尚未在生产部署。
000002_task_api 增加任务分页索引,将业务参数、结果、回执、流程定义/输入/输出等字段改为校验过的 JSON 文本,避免原生 JSON 数字重编码。公共 Go JSON 扫描类型保持兼容,原模型职责不变。响应 DTO 与持久化模型分开;SQL 空结果先扫描到可空字节切片再转换,避免驱动与 json.RawMessage 的可空类型不兼容。
000004_execution_history 为已有证据表增加 `(namespace_id, attempt_id, created_at, id)` 分页索引,不新增实体或字段,不回改已有迁移。尝试列表复用执行代次唯一索引。查询 DTO 与持久化模型分离,只在详情读取业务正文,不返回执行秘密或内部摘要;接口见 [执行历史](api/execution-history.md)。
000005_safe_retry 增加任务 EffectUncertain、尝试与证据 Retryable 字段,Go 与 SQL 均附中文说明;实体数仍为 32。跨尝试的不确定效果必须保留,历史 NEEDS_REVIEW 保守回填 true,旧状态、版本和冻结策略不变。回执增加 `(namespace_id, attempt_id, operation, request_digest)` 索引,换消息身份重报结果也返回原已应用回执。字段语义、升级策略启用与限制见 [安全重试](api/retries.md),升级回归见 [阶段报告](reports/phase-3-safe-retry.md)。
000006_schedule_runtime 增加 Schedule.QueueID / ProcessingVersion / CheckAt 以及 ScheduleVersion.CatchupWindowMS / GraceMS。字段、单位、可空语义均有中文注释;CoveredUntil 明确为合并或跳过范围的排除边界。实体数不变,增加扫描、列表和任务来源索引。时间规则 JSON 冻结 CalendarVersion,服务内置相应时区快照。调度记录、生成任务、事件和进度同事务写入,旧版本积压不会被新发布覆盖;详见 [计划契约](api/schedules.md)。
000007_task_cancellation 允许尝试证据记录 CANCELLED,不新增实体;取消意图、结果和历史不确定效果的规则见 [取消契约](api/cancellation.md)。
000008_no_foreign_keys 移除历史 70 个外键,保留索引、唯一约束、CHECK、触发器和数据。旧迁移已在回归库应用,按不可变校验和约定保留原文件;已有库继续按历史链前向升级。新装库由迁移器使用当前版本的无外键基线直接建表,再登记 1–30 的不可变校验和,因此初始化过程也不会先创建历史外键;基线版本变化时必须随新迁移重新生成并回归。后续迁移禁止再引入外键。升级旧库时先停用旧服务,应用完整迁移再启动新版;迁移需要 DDL 锁,应在目标部署环境演练维护窗口。
000009_queue_resources 增加 Queue.MaxUnfinishedTasks、UnfinishedTasks、StartWindowUntil、StartsInWindow,Go 字段与 SQL COMMENT 均有中文语义,实体仍为 32。未终结任务按 WAITING/LEASED/RUNNING/NEEDS_REVIEW 回填;窗口初始为空、计数为零。运行计数与任务/开始授权同事务维护,不改变队列配置 revision,配置变更不能重置它们。降额允许已有使用量暂时超过新上限,不删除任务或撤销已有许可;详见 [队列契约](api/queues.md) 和 [资源回归](reports/phase-3-queue-resources.md)。
命令与验证记录见 [开发计划](08-development-plan.md)、[基础阶段验证报告](reports/phase-0.md) 与 [取消及无外键回归](reports/phase-3-cancellation.md)。历史阶段报告描述当时结构,当前约束以本页为准。
## 12. 应用共享额度
000010_application_resources 新增 ApplicationResources,使用 BINARY(16) 应用主键,12 个持久化字段均有中文注释和 SQL COMMENT,无外键。共享未终结任务数、活跃尝试数、未开始预占数与一秒开始窗口;配置 revision 不随用量变化。停止旧写入节点后回填所有应用,包含跨命名空间的既有在途状态。关联身份行与额度行分开,认证后按应用额度 → 队列 → 任务/尝试 → 许可顺序持锁。后台恢复不因应用停用而停止释放到期尝试。详细字段、权限、SDK 场景及并发边界见 [应用配额接口](api/application-resources.md)。
## 13. 显式资源键许可
000011_keyed_concurrency 增加 Task.ConcurrencyKey / ConcurrencyKeyDigest、Attempt.ConcurrencyToken、WorkerSession.ConcurrencyKeys,共四个中文注释与 SQL COMMENT 字段。历史值分别为空/空、零和 false,原 BusinessKey 语义不变;截至 000011 为 33 个实体、273 个直接声明的持久化字段,最终外键数保持零。
资源限制复用 ConcurrencyLimit:scope_key=key,key_digest 为域分隔 SHA-256,命名空间内唯一;每键最大许可固定 1。原始 UTF-8 字节精确匹配,不依赖 MySQL 的文本排序规则。一个有键尝试持有队列和资源键两条 Permit,应用活跃尝试只计一次;续租、释放、恢复与状态同事务完成。
键行 Revision 在领取和释放时递增,领取后的值保存到 Attempt.ConcurrencyToken;同尝试重连不改变序号,资源行不得删除或重置。达到整数边界时拒绝新领取,禁止回绕。SDK 交付序号,资源端负责原子比较与业务幂等;历史未知效果与执行许可释放分别维护。字段、升级、调用和异常语义见 [资源键契约](api/keyed-concurrency.md)。
## 14. 任务优先级和节点公平领取
000012_dispatch_priority 开放既有 Priority,范围 0–9,并增加对应 CHECK。新增只读生成列 DispatchAt(AvailableAt 减 Priority 乘30秒)及 `(namespace_id,queue_id,state,dispatch_at,available_at,id)` 排序索引;历史默认优先级 0 的排序时间等于 AvailableAt。Generated 字段随退避和恢复自动重新计算,不允许独立写入。33 个实体、274 个直接声明的持久化字段全部保留中文注释,新增 SQL 字段和 Priority 的 COMMENT 同步更新,无外键。
派发先检查实际到期、截止、能力、门控和资源键,再按排序时间选择。节点公平领取池根据认证后的 ApplicationID 分组,再按命名空间/队列轮转;内存队列和短期空探测缓存可在重启后重建,不保存授权事实。详细约束、SDK 和升级步骤见 [优先级与公平派发](api/priority-and-fairness.md)。
## 13. 可靠结果订阅核心
000013_result_subscriptions 新增 EventStream、ResultEvent,扩展 Subscription 和 Delivery。289 个直接声明字段均有中文注释。生产事务在独立流行锁下分配序号,与任务、原事件和结果快照一起提交;消费事务不锁流行、任务、队列或应用额度。交付记录和扫描位置一起落库,每条交付单独持有租约和证明。重复确认不重复扣减积压,耗尽保留记录,人工追加预算不重置历史。详见 [订阅核心](09-result-subscription-core.md)。对外 HTTP/WSS、管理与消费 SDK 已实现,持久化 Inbox 完整场景已交付。
## 14. 交付历史查询索引
000014_delivery_history 增加按订阅及可选状态过滤的创建时间分页索引,领取、确认和重试不改变排序键。不增加模型字段或外键,仍为35个实体、289个中文注释字段。查询按凭据所有者、命名空间和订阅校验,游标绑定过滤条件;详情按来源事件ID读取不可变快照且不返回交付秘密。见 [订阅查询接口](api/subscriptions.md)。
## 15. 独立接收方示例模型
[result-inbox示例](examples/result-inbox.md) 在业务方自己的数据库建立receiver_inbox和receiver_task_views,2个实体、17个Go/SQL中文注释字段,无外键。它们属于独立示例模块,不计入平台35个实体,也不加入平台迁移。Inbox去重记录与业务视图同事务提交;视图仅按更高任务版本推进,重复和迟到事件不能重复更新或回退业务结果。
## 000015 人工恢复及重试关联
复用现有Task.RetryOf与AuditEvent.EvidenceRef,仍为35个实体、289个直接声明的持久化字段。RetryOf中文注释/SQL COMMENT明确“同命名空间每个原任务最多一个直接后继”。迁移将历史普通索引fk_pulse_tasks_3替换为相同列(namespace_id,retry_of)的唯一索引uq_task_retry_parent,并增加禁止自身关联的CHECK;该历史名字表示留下的索引,不是重新增加外键。
核查和重试按认证→应用额度→操作幂等→队列→任务/尝试持锁,事务内校验状态、父任务/计划归属和无活动执行。核查的状态/result、额度释放、审计、回执及结果日志一起提交,结果流锁最后取得。人工重试创建新任务与受理事件,审计关联保存在原任务上;旧终态、旧尝试和迟到证据不覆盖。详见[接口契约](api/task-recovery.md)。
真实v7升级回归检查70个外键全部删除、原任务保留、323个未替换索引组件不变,并单独核验新的重试唯一索引覆盖原两列。已有非法重复重试关联或自关联不会被静默清理;迁移失败需核查实际数据。后续仍禁止外键及级联。
## 000016 任务业务键及创建时间查询
BusinessKey沿用既有可空VARCHAR(191),Go/SQL中文注释明确精确匹配、区分大小写和尾部空格;排序规则显式utf8mb4_0900_bin,历史文本原样保留,不增加模型字段。新增(namespace_id,queue_id,business_key,created_at,id)及增加state的组合索引,配合原两种创建时间索引覆盖有无状态/业务键的四种查询。
HTTP/SDK创建时间范围使用包含下界、不包含上界;v2游标以固定长度摘要绑定全部规范化筛选,当前权限逐页校验。单项提交、计划生成和人工重试仅把Go空字符串映射为NULL,不用连接排序规则折叠空格。仍为35个实体、289个中文注释字段,无外键/级联;具体接口与升级边界见[查询手册](api/task-queries.md)。
### 任务直接来源视图
[来源查询](api/task-source.md)复用Task.OwnerKind/OwnerID/RetryOf、Schedule、ScheduleVersion与ScheduleOccurrence,沿已有(namespace_id,task_id)唯一索引及计划版本键定位,不增加表、持久化字段、索引或迁移。只读响应模型的每个字段也有中文注释。任务、计划、触发版本与队列归属在认证事务中显式验证,缺失关联不被默认为普通任务;流程来源已实现,见本页末尾。
### 业务事务Outbox示例模型
[独立task-outbox](examples/task-outbox.md)包含sender_outbox和sender_jobs,2个业务实体、22个Go/SQL中文注释字段,无外键;不计入平台35个实体和289字段。Outbox保存固定命名空间/队列、业务操作、原提交键/请求/摘要、状态/次数/代次/到期时间及原受理回执,业务行同事务创建和关联。命名空间与队列范围内按wake_at索引领取,终结状态wake_at为空;发送次数与总发送期限有界。
## 相对延迟的持久化边界
delay_ms是普通/批量提交命令字段,首次事务以同一个数据库时间写入created_at和available_at;不增加表字段、迁移或外键。原时长参与幂等请求摘要,原回执保存初始时间;重报不能重新计时。后续安全重试可以更新当前available_at,首次受理回执及历史尝试仍保留。Go命令字段提供中文说明,见[任务契约](api/tasks.md)和[回归报告](reports/phase-3-delay-recovery.md)。
## P4 内部结果快照
000017_workflow_result_inbox为InboxEvent增加SourceTaskID、SourceActivationID、SourceRevision、Snapshot四个直接字段;当前35个实体、293个直接声明持久化字段,均有中文注释,无外键或级联。有效待处理记录要求来源齐全;历史缺少快照的未处理记录隔离为QUARANTINED,保留旧代次而不重建结果。内部快照独立于对外结果日志保留期,和Pulse权威结果同事务提交。见[执行决策及交付边界](10-workflow-engine-core.md)与[回归进展](reports/phase-4-engine-core.md)。
## 实例受理与等待身份(000018)
Wait新增SignalName和PayloadVersion两个中文注释字段;correlation_key转为VARBINARY(764),新受理仍限制512字节,兼容历史191个四字节字符而不截断。实例business_key使用utf8mb4_0900_bin保留精确尾部空格;仍无外键和级联。35个实体,含公共Record的295个直接持久化字段声明均有中文注释。内部`$root`步骤作为实例级待续检查点,不属于定义静态节点或公共步骤列表。具体初始事务、预算和未接通的运行边界见[实例受理](11-workflow-admission.md)。
## 等待时钟回填(000019)
复用PendingAdvance保存ROOT、TIMER、POLL检查点;新增内部JSON结构字段均有中文注释,不新增持久化列或实体,截至该迁移为35个实体/295个直接持久化字段。TIMER/POLL检查点固定激活ID,实际推进核验同命名空间归属、原截止及剩余预算。迁移只回填历史有效等待的唤醒身份和时间,保留已有检查点;无外键、无级联,见[时钟运行约定](13-workflow-clock.md)。
## 信号身份与赢家增量(000020)
Signal新增payload_version、target_activation_sequence、evidence_ref、disposition、available_at;Wait新增winner_signal_id。截至000020为35个实体、含公共Record的301个直接持久化字段声明,全部中文注释。新信号精确关联最多512字节,存储兼容历史764字节;过期检查退避不改变expires_at。赢家唯一约束只防重复,实例/等待/激活/信号归属及不可变受理证明仍由事务验证,外键保持0。历史不完整身份隔离和升级回填见[信号约定](14-workflow-signals.md)。
## 停止意图增量(000021)
Instance新增StopKind和StopRequestedAt,冻结首次用户取消或失败结清目标;CancelRequestedAt仍只表示用户显式取消。成对CHECK防止半条意图,任务所有者索引支持双向归属核验。截至000021为35个实体、303个直接持久化字段声明,均有中文注释。历史停止实例关闭门控并恢复根接续,不改变原截止、预算、控制版本或终态数据;保持零外键,详见[控制约定](15-workflow-controls.md)。
## 流程人工核查与TASK新激活
复用现有激活sequence、任务retry_of、审计和幂等回执,不增加表、字段或外键。TASK人工重试以新激活保留旧执行,原尝试预算跨激活扣除,原绝对截止不改变;执行核查和步骤逻辑结论分别保存。此阶段为35个实体、303个中文注释字段;后续POLL恢复增加2个预算字段,见下节。核查操作见[核查约定](16-workflow-recovery.md),独立等待恢复见[等待恢复](18-workflow-wait-recovery.md)。
### 000022:跨激活保留查询轮次与尝试
PollState新增FirstRound和FirstRoundAttemptsUsed,记录当前激活的首个业务轮及该轮在旧激活已消耗的尝试。UsedRounds继续使用首次激活起的业务轮编号;原单轮尝试和查询/请求绝对截止均不重置。新业务轮恢复原单轮策略,人工恢复同轮只分配剩余尝试。当前35个实体、305个直接持久化字段声明,Go/SQL均有中文注释,无外键。v21升级保留旧数据、时间和预算,详情见[查询恢复](17-workflow-poll-recovery.md)。
### 等待恢复与PENDING接续
复用现有激活、等待、查询状态和不可变审计,不新增迁移或字段。RearmWait以新代次保留首次等待截止;ContinuePoll保留当前代次和原轮次,以权威已处理结果及管理审计恢复间隔。仍为35个实体/305个中文注释字段,无外键,见[等待恢复](18-workflow-wait-recovery.md)。
## 流程任务直接来源
[WORKFLOW来源](api/task-source.md#5-流程固定来源)复用实例固定版本、步骤、激活、查询轮次及Task.RetryOf;不增加迁移、表、持久化字段或外键。响应模型和独立SDK新增字段均有中文注释,仍为35个持久化实体/305个直接字段声明。沿已有任务唯一索引和步骤代次唯一键核验正反向归属,只返回直接父任务;人工恢复不改写旧任务的历史激活来源。
## 流程历史查询索引
000023_workflow_signal_history只为weave_signals增加(namespace_id,workflow_id,accepted_at,id)分页索引,保留全部原信号数据和状态。仍为35个持久化实体/305个直接字段声明,无新增字段或外键;HTTP/SDK的摘要和详情字段均有中文注释。[历史查询](api/workflow-history.md)明确区分当前逻辑步骤与指定历史激活,不以当前代次替换旧来源。基础测试禁止000008之后再次引入数据库引用约束,真实MySQL升级及readiness验证外键为0。
## 固定版本查询范围与实例分页(000024)
VersionScope新增6个中文注释字段:命名空间、定义版本、定义、原摘要、去重队列JSON、索引创建时间;当前36个实体、311个直接持久化字段声明,全部有中文注释。版本范围不可更新,发布与范围同事务,读取摘要还要核验原定义和关联,不以派生索引授予权限。回填仅遍历DSL步骤,忽略常量中相同字段;旧版本及实例原文不修改。
7个新实例复合索引加现有业务键索引覆盖定义/业务键/状态8种组合,按创建时间与ID分页;全部保留无外键和无级联。范围校验、迁移性能边界和接口见[查询手册](api/workflow-queries.md)。
## 流程事件派生索引(000025)
Event.WorkflowID为只读STORED生成列,从原不可变事件派生流程归属,非流程或非法标识为空;应用不得独立写入,也不能将它作为授权依据。索引为(namespace_id,workflow_id,occurred_at,id)。历史原文不变,不补造过去缺失的信号转换;当前36个模型、312个直接持久化字段均有中文注释,无外键及级联。
新运行器将PENDING信号的消费、拒绝或过期与原状态事件同事务保存,批量拒绝分32条追加但整笔事务原子提交。公开查询核对固定版本全部队列、步骤/信号归属及历史激活。原始事件按数据库记录时间分页,版本与时间均不构成可靠消费水位。详见[状态时间线接口](api/workflow-events.md)与[验证报告](reports/phase-5-events.md)。
升级先停止旧写入节点,应用000025再启新版本,防止混合节点继续遗漏信号转换;生成列和索引涉及历史行扫描与可能的表重建,需预演维护窗口、磁盘和锁等待。严格SQL模式下先校验十六进制字符再转换,异常历史范围保留NULL,不清理原记录。
## 有界业务观测索引(000026)
000026只增加三组读取索引:`pulse_tasks(state,available_at,id)`、`orbit_deliveries(state,available_at,id)`和`weave_instances(state,updated_at,id)`。它们服务于后台有界观测,不改变任何模型字段、状态机、事务边界或授权规则,也不包含外键或级联。采样器只使用代码固定的表、索引、状态和列名,每个状态最多读取10000条;结果达到上限时必须通过指标暴露截断,不能把样本数解释为全库精确数量。迁移后仍要求服务层 `CheckSchema` 验证零外键,真实升级见[有界业务采样报告](reports/phase-6-business-observability.md)。
000027为`orbit_events(type,occurred_at,id)`增加固定事件窗口索引。采样器只读取代码列出的任务和流程事件类别、最近5分钟、每类最多10000条;未知事件类型不写入标签,事件指标只说明本节点有限趋势,不能代替审计查询、端到端阶段延迟或跨节点吞吐。索引不改变事件原文、不可变触发器、外键策略或事务边界。
000028为`pulse_tasks(state,completed_at,id)`和`weave_instances(state,completed_at,id)`增加终态耗时样本索引。采样器只读取最近5分钟内成功、失败或取消记录,最多10000条,计算创建到终态的平均/最大秒数并在截断时复用统一标记;不把该样本解释为端到端外部效果或全局SLO。
## 控制台身份与历史保留策略(000029–000030)
000029增加 `orbit_console_users` 和 `orbit_console_sessions`,只保存控制台账号的 bcrypt 哈希、绑定凭据及 HttpOnly 会话摘要;不保存密码或令牌原文。控制台继续单管理员模型,服务层每次修改前核对会话、命名空间和绑定凭据权限。
000030增加 `orbit_retention_policies`,按命名空间保存归档开关、幂等/任务/流程/事件/交付/Inbox/审计窗口、修订号及时间。所有字段都有中文 COMMENT,策略不含外键或级联。数据库策略优先于部署默认值;默认关闭归档,配置变化不触发删除。服务层用同一事务完成版本核对、幂等回执和审计快照,并在归档预览/导出时保护未确认交付、未知效果、未结束流程和有效幂等身份。具体窗口、候选目录和控制台接口见[数据保留与归档策略](api/retention.md)。
## 文件归档作业模型
`internal/retention` 中的 `JobSpec`、`JobManifest`、`JobBatch` 和 `JobStatus` 定义固定作业范围、不可变清单、连续批次及汇总状态;各持久字段提供中文注释。它们只存入私有归档目录,不新增数据库表。连续文件与摘要链就是恢复检查点,作业 `JobID` 进入现有管理审计的执行者身份。协议与失败边界见[文件归档作业](api/retention-jobs.md)。