# 群组时间线与同步

[群组托管协议](../README.md) · [群组模型与密钥](model-and-keys.md)

## 群时间线与同步规则

每个群只有一条按 `sequence` 严格递增的时间线，创建位置为 0，后续不要求连续。客户端签署的管理事件按[管理链](../core-objects.md#参与事件与前序引用)规则关联；消息和中继主动轮换不推进管理链。写操作遵循[原子提交与持久化规则](../methods/conventions.md#原子提交与持久化规则)。

客户端通过 [`group.sync`](../methods/lifecycle-and-sync.md#groupsync) 读取全部管理事件和授权区间内的消息，并按该方法及[管理链](../core-objects.md#客户端验证与恢复)规则验证事件、重建状态。客户端可以逐个事件或分批更新同步位置。后续事件处理失败不影响此前已完成事件的结果和对应进度，但同步位置不得越过尚未按本协议完成处理的事件。

## 群组同步与恢复流程

成员在设备上首次加载群或断线重连时，可以参考以下同步流程：

1. 确定 `group_id` 和托管中继，建立设备会话。缺少群私有状态时，向同账户设备发送 [`AccountGroupPrivateStateRequest`](account-sync.md#accountgroupprivatestaterequest)。
2. 使用 WebSocket 接收通知时，先提交 [`group.subscribe`](../methods/subscription.md#groupsubscribe)，成功后开始补齐数据。仅使用 HTTP 同步时跳过订阅。
3. 调用 [`group.sync`](../methods/lifecycle-and-sync.md#groupsync) 补齐事件并验证、重建群状态；所需版本的密钥材料本地缺少时，按需调用 [`group.key.sync`](../methods/keys.md#groupkeysync)。
4. 管理历史验证到某一密钥版本，且对应密钥材料可用后，按 `group.key.sync` 的规则恢复或复用该版本已验证的应用秘密；对应消息事件到齐后，即可处理消息。历史密钥缺失不阻塞当前版本恢复。
5. 同步期间及完成后，按[通知处理规则](../../notifications/README.md#通知处理规则)过滤或合并提示，需要补同步时从已完成位置继续补齐事件，并按需补齐密钥。

## 群组数据保留与访问规则

### 事件与状态保留

`relay.info` 声明的 `group_message_retention` 是消息事件的最低保留期限；截止时间由消息的 `accepted_at` 和接受时的期限确定，截止后可以清理。群消息幂等结果的保留规则见[群消息幂等重试](../methods/messaging.md#群消息幂等重试)。

管理事件及验证其签名所需的设备证书永久保留，包括群创建、客户端管理操作和中继主动轮换。申请和密钥重置请求的原始材料按各自业务生命周期保存。

群存续期间持续保留当前群状态、内部成员和封禁状态、设备访问权限及有效业务记录。消息清理不改变这些状态，不回退时间线头或管理链头，不复用序号。

### 密钥材料保留

当前密钥及仍在保留期内的消息所需密钥不得提前清理。

群存续期间，中继必须保留每个当前成员解开当前客户端群秘密所需的密钥盒。

旧中继秘密和相应盒至少保留至最后一条依赖该版本的消息到期。清理后 `group.key.sync` 不再返回该版本。缺少对应旧成员私钥时，无法解开历史客户端秘密盒；已有经验证的对应历史应用秘密时，可以直接派生消息密钥，无需重新解开密钥盒。需要长期消息历史的客户端应在期限内保存正文、附件引用及相应版本的群应用秘密。

### 读取权限与群关闭

当前有群读取权的设备可以读取全部管理事件，消息仅在其授权区间内可读。离群、被移除、被封禁或设备当前无权限时拒绝读取。群关闭后不保证继续提供读取服务，也不承诺消息和密钥保留。
