Skip to content

Realm State Snapshot Schema

This content is not available in your language yet.

Realm 状态快照

规范关键字按规范语言解释。机器契约为 realm-state-snapshot.schema.json,bootstrap 与治理 Station 更换规则见治理提交日志。

1. 目的与边界

Snapshot 是加速恢复的派生物,不是真相源。真相源是 producer-signed Event 与当前治理 Station 签发的 RealmCommit。Snapshot 必须绑定 Realm、authority generation、签发时各个可见 stream head、内联 typed current rows、对应 history floor、创建时间和 Station proof。closed wire 成员是 snapshot_id、 realm_id、governance_generation、visible_stream_heads[]、current_state_entries[]、 retention_and_history_floor、created_at 与 signature。v1 没有额外的 sections、chunk/chunk digest、 state root 或 Blob 引用层;不得把旧 replay 容器作为此 schema 的兼容分支。

2. 可见 stream heads

visible_stream_heads[] 对接收者获准读取的每条 Realm、Circle 或 Sidecar stream 分别记录 stream_ref、 stream_position 与 realm_commit_id。不同 stream 的 position 不能比较,也不能由数组顺序推导总序。

普通 joiner 的 snapshot 只列出其当前可见 stream;因此它只能验证这些 stream 的连续性,不能证明隐藏 Circle 或 Sidecar 不存在。planned authority handoff 使用单独的私有 full-stream-head manifest,不能从公开 authority bundle 或普通 join snapshot 获得隐藏 stream 列表。

3. Typed current rows

current_state_entries[] 的每个元素必须是 typed-current-result.schema.json 的 closed typed result; 其 selector、revision 和 value 由各 family 的 schema 决定,不额外包一层通用 row/chunk。当前治理 Station 必须从同一 durable cut 读取全部可向该请求者披露的 rows、visible_stream_heads[] 和 stream floors, 不得把无权 Circle/Sidecar 的 row、head 或 floor 混入;同一完整 typed subject 不得出现两个 current row。 接收方须以每条 row 必填的 source_stream_ref 定位可见 head 与 floor,验证其 Realm/stream 属于本次可见范围、 revision 的位置不晚于该 stream 的可见 head;不得从 selector 或同值 position 猜来源。可读取到 revision 所指 Commit 时还须逐字核对其 stream、commit id 与 position。落在获授权 history floor 之前的 row 由当前治理 Station 的这份签名 snapshot 承诺,不能要求受限接收者下载不可见前史来补证; 范围或坐标不一致时整份丢弃。

Relation 使用已登记的 relation result:selector 是完整 primary_conflict_domain, value 是该 domain 唯一的完整当前 Relation(含 active 或 tombstoned 状态),不另造按 RelationId 选取的 current 身份或冲突集合。它的 source_stream_ref MUST 等于当前 value 的源作用域; Circle scope 不进入 primary-domain 身份。除源 Realm/Circle 成员可见性外,完整 row 还 MUST 满足 ../models/relation.md §4 对两个 endpoint 的 reference-disclosure 要求。无权、未知或不可证明可披露的 endpoint 不得通过 Snapshot 泄露; 该完整 row MUST 省略,不能将 locked stub、部分 Relation 或未授权 target-side reverse edge 写入 canonical current_state_entries[]。重取旧 Snapshot 时也必须重新执行同一披露判定。

内容型与状态型 family 的披露(normative):「可向该请求者披露」按 family 性质分两类。 message_revision 是 v1 唯一的内容型 family:它的 value 就是承载 Event 的 create/revise payload,即历史内容。 它的 row 只在同时满足下列两条时进入 snapshot:(1) row 的 covering Commit(revision 所指)位于请求者在 source_stream_ref 上的可读区间内,即不早于该 stream 的 caller readable floor(since_join 成员为其当前有效 join Commit,见 ../governance/history-visibility.md §3.1)——不满足时 请求者本来也不能经 scan 读到承载该 value 的 Event;(2) 该 Message 没有 ak:message: 拼写的 object_redaction row——已撤回 Message 只下发其 object_redaction row,原 payload 不得经 snapshot 恢复 (../models/strand-and-message.md §9.5.1)。其余 family 都是状态型,按 membership 与 scope 可见性披露,不受 history floor 限制:Realm 共享状态向全部 joined 成员可见,floor 只约束 内容历史。按 snapshot_ref 重取已签发 snapshot 时同样按请求者当前可读区间与当前撤回状态重验,已含不再可披露 message_revision row 的 snapshot 对该请求者不可用。接收方 MUST 接受「只有 object_redaction、没有 message_revision row」的 Message,也 MUST NOT 把 floor 以下 Message row 的缺席当作缺口。 从 snapshot 边界之后的逐 stream tail 继续运行同一 typed reducer,不得用 generic patch、 typed current result merge 或 wall-clock last-write-wins 修补差异。current_state_entries: [] 仅在该 cut 确实没有可披露 current row 时合法;它不是要求另取 chunk 的占位符,也不能证明隐藏 row 不存在。

4. 创建与验证

Snapshot 的 signature 使用 ak.realm_snapshot_signature.v1。unsigned projection 是从完整 closed Snapshot 删除 signature 后保留的全部实际存在成员;验证方对其作 RFC 8785 JCS,重算 sha256:lowercase_hex(SHA-256(unsigned_bytes)),先与 envelope 的 signed_digest 逐字比较,再验证 UTF8("ak.realm_snapshot_signature.v1\n") || RFC8785_JCS({context,signature_algorithm,verification_method,signed_digest,created_at}) 上的 64-byte Ed25519 签名。当前 /head snapshot 的 governance_generation 必须等于 fresh current authority bundle 的当前任期, 其 verification_method 必须是当前 Station 的 service signing key。按已发出 snapshot_ref 读取的历史 exact snapshot 可属于更早任期; 接收方必须由同一 fresh current authority bundle 的完整 genesis-to-current 历史链定位该 generation 当时的治理 Station, 以该 Station 在 snapshot 签署时有效的 exact service signing key 验签。未知 generation、链外 Station、旧 key 代签新任期均必须拒绝; 不能拿当前 Station key 替旧任期签名,也不能把已被取代的 snapshot 冒充当前 /head。

当前治理 Station 在同一一致性快照中读取 visible stream heads、current_state_entries[] 与 history floors,构造 canonical body, 计算 snapshot ID 并签名。接收方必须验证:

  1. fresh current authority bundle 证明签名 Station 是 snapshot 的 governance_generation 当时的治理 Station;当前 /head 还必须处于当前任期;
  2. snapshot ID 与 canonical body 匹配;
  3. Station proof 的 domain separation 与 payload digest 匹配;
  4. 每个 visible head 可由随后下载的同 stream tail 连续承接;
  5. tail 中每个 Commit 的 Event、producer proof、authority proof 与 typed reducer 均有效。

任一项失败时必须丢弃整个 snapshot,不能部分采用 rows。Snapshot 签名使当前治理 Station 对 该 materialization 负责,但本身不提供独立 omission proof;随后 tail 的逐 stream 连续性只能 证明从各自已验证 head 起的后续 Commit 没有缺口,不能反证该 head 前被治理方隐去的 row。

5. Join bootstrap

邀请人服务器和 Directory 只提供候选 locator。Joiner 向候选发送 fresh nonce,取得 genesis-to-current 的 nonce-bound authority bundle,验证后只从该 current governance Station 拉取 snapshot 与自己可见的所有 stream tails。邀请中缓存的“初始 Station”或 genesis Station 不能覆盖已验证的 current authority。

6. Planned handoff

旧 Station 私下向新 Station 交付 snapshot、完整 stream-head manifest 及每条 stream 的缺口材料。公开 handoff certificate 只披露 Realm stream head 与 full manifest digest。新 generation 在每条既有 stream 上的 第一笔 Commit 必须以前一 generation 导入的该 stream head 为 previous_commit_ref,位置加一;它们彼此没有 统一的“handoff 后第一笔”顺序。

若旧 Station 丢失且未完成双签 handoff,v1 不自动选主,也不允许新 Station从成员投票或最长链自行接管。 恢复必须走 Realm 明确声明的外部恢复政策或创建新 Realm。