# 客户端—中继通知

[客户端—中继协议](../README.md)

## 通用通知规则

### 通知封装与兼容处理

服务端通知只通过 WebSocket 发送，使用 JSON-RPC Notification。通知的 `jsonrpc` 必须为 `"2.0"`，必须省略 `id`；`method` 是通知名称。相应通知定义了参数对象时，`params` 必须使用该完整对象；无参数通知可以省略 `params` 或使用空对象 `{}`。

通知封装的外层未知字段按 [WebSocket JSON-RPC](../methods/conventions.md#websocket-json-rpc) 规则忽略；已定义的通知字段和 `params` 仍按各自约定验证。

客户端不对通知返回响应。未知通知必须忽略，以便以后增加新的通知类型。通知可以与 JSON-RPC 响应交错发送。

### 连接与会话要求

只有设备会话连接可以建立订阅并接收设备状态、消息、频道或群组通知。通知可以合并、重复或丢失，不能替代相应的读取或同步方法。

原连接[会话续期](../methods/authentication-and-sessions.md#websocket-会话续期)成功时，保留仍有效的通知启用状态和订阅。当前访问权限和设备撤销规则继续适用。

### 通知处理规则

通知须满足其连接身份、会话、订阅和对象绑定要求。比较通知位置或版本时，必须限定于同一可信网络上下文、中继、资源及当前设备的相应处理范围；不能跨账户、频道、群或设备复用已完成位置。

携带 `head` 的通知，如果该位置不大于本地相应的已完成同步位置，可以直接忽略。其他尚待处理的通知可以合并，由一次补同步共同处理。收到通知或发出读取请求本身不推进同步位置；同步位置按相应读取方法的处理规则确定。补同步是否完成以相应读取方法的响应和处理结果为准；过滤、删除或清理可能使最后一项可读记录小于通知中的时间线头。

不携带可比较位置或版本的通知，只能按同一对象合并尚待处理的刷新需求，不能仅凭通知参数相同、本地已有缓存或刚完成一次读取就判定它过时。分页读取开始后收到的列表变化提示，若无法确认已被本次遍历覆盖，应省略游标重新读取，不能仅因读完剩余页就清除刷新需求。

读取期间新收到的提示若无法确认已被该次读取覆盖，仍须保留刷新需求并补读；读取失败或处理未完成也不得视为需求已经满足。

通知过滤或合并不能清除已知历史缺口或其他尚未满足的同步需求。

## `device.state.changed`

账户当前归属中继接受新 `AccountDeviceState` 后，通过 `device.state.changed` 通知该账户仍有效的在线设备会话连接，包括发起本次状态提交的设备所建立的其他连接。账户会话不接收通知。被新状态移除的设备会话连接直接失效，不接收通知。预存状态不产生通知。

### 通知参数

| 字段 | 类型 | 必需 | 语义与约束 |
|---|---|---|---|
| `revision` | integer | 是 | 触发本次通知的已接受 `AccountDeviceState` 的版本；必须是非负[安全整数](../../general.md#安全整数与计数器推进) |

### 处理规则

客户端在同一可信网络上下文和本账户范围内，将通知的 `revision` 与本地已验证并保存的完整设备状态版本比较；通知版本不高于本地版本时，可以忽略该通知。没有这样的本地状态，或者通知版本更高时，客户端调用 [`device.state.resolve`](../methods/device-state.md#devicestateresolve) 读取自身完整设备状态，验证后更新缓存。

同一账户尚未处理的提示可以按最高通知版本合并。只有读取结果通过验证，且其 `revision` 不低于尚待处理的最高通知版本时，才能确认这些提示已被覆盖；读取期间收到更高版本的通知，或读取失败、结果版本仍较低时，按[通知处理规则](#通知处理规则)保留刷新需求并补读。

通知不携带完整设备状态，也不作为设备状态证明。收到通知不得直接推进本地已验证版本或改变设备权限；忽略或合并通知不得清除其他尚未满足的刷新需求。

## `message.timeline.changed`

本通知仅在账户当前归属中继的 WebSocket 连接上启用。设备在该连接上首次通过 `auth.device.verify` 时，中继必须先发送认证成功响应，再自动启用本通知。

### 通知参数

| 字段 | 类型 | 必需 | 语义与约束 |
|---|---|---|---|
| `head` | integer | 是 | 触发本次通知的记录追加完成后，中继所见的账户消息时间线头；必须为非负整数 |

### 处理规则

该通知只提示当前设备可能存在尚未同步的记录。客户端按[通知处理规则](#通知处理规则)处理提示，需要补同步时调用 [`message.timeline.sync`](../methods/messaging.md#messagetimelinesync)。`head` 可能对应仅对其他设备可见的记录，不能把达到该值作为补同步完成的条件。

建议客户端在当前归属中继的 WebSocket 连接首次通过设备认证后调用 `message.timeline.sync`，补齐通知启用前可能遗漏的记录；原连接续期本身不要求额外同步。同步位置按[消息时间线处理流程](../concepts/message-timeline.md#消息时间线处理流程)确定。断线、通知丢失或中继重启后，也从该位置补同步。没有 WSS endpoint 或连接尚未恢复时，客户端应周期性同步。
