Meshline
简体中文规范下载 Markdown 原文

中文为规范基准;英文为维护译本。

中继—推送网关协议

Meshline Protocol 1.0

本协议规定推送网关地址的获取方式,以及中继向网关发送消息通知的报文、认证和交互规则,能力标识为 push.notify.v1。

网关声明与能力

设备通过 DeviceCertificate 中的 push_gateway 声明完整回调地址。省略表示没有声明网关。该地址可随设备证书传播;不得在地址或证书中放入推送平台用于定位设备的标识、回调密钥或平台凭据。

中继通过 push.notify.v1 声明遵循本协议的推送能力。

地址来源与更新

中继通过已验证的设备证书获取推送网关地址。网关声明在本网络内按 (account, device_id) 区分;采用设备证书时,以其中的 push_gateway 更新声明,字段省略时清除原声明。连接关闭或会话到期不清除声明。

中继确认设备不再获得账户授权时,清除其网关声明;恢复授权后,须重新取得并验证设备证书。发送通知时遵循发送目标验证。

网关地址

push_gateway 必须是具有有效主机的完整绝对 HTTPS URL:以 https:// 开头,最多 512 UTF-8 bytes,允许 query,不得包含空白、fragment、userinfo 或反斜杠;空 fragment 也不允许。

该完整地址就是接收端点,中继不得追加固定路径。设备证书和通知中的 push_gateway 必须保留原地址;不得通过补齐路径、删除部分、大小写转换或其他改写后接受不合规地址。目标地址绑定按完整字符串逐字比较,不按 URL 等价关系比较。

地址格式验证不依赖当时的 DNS 可用性。每次实际连接还须满足回调连接安全。

PushNotification

每个通知只面向一个接收设备。字段表示和未知属性遵循协议总则。

字段 类型 必需 语义与约束
$type string 是 固定为 meshline.push.notification
network string 是 完整规范网络上下文,同时包含 Neo network magic 和 Registry 合约地址
relay_id string 是 报告事件的中继 ID
public_key string 是 33-byte SEC1 compressed secp256r1 公钥,无 padding base64url;必须派生出 relay_id
push_gateway string 是 本次接收端点,满足网关地址规则
issued_at integer 是 本通知签发时的非负 UTC Unix 秒
message_type string 是 中继可见的原始消息对象的 $type,须逐字保留;非空,不限定枚举值
to string 是 接收账户的账户 ID
to_device_id string 是 接收设备 ID,遵循设备 ID格式
message_id string 是 原始消息 ID
from string 是 发送账户 ID
accepted_at integer 是 本中继记录的原消息接受时间,非负 UTC Unix 秒
sequence integer 是 原记录在本中继上的时间线位置,非负安全整数;具体取值遵循原记录的约束
sender_nickname string 否 发送账户的公开昵称,取自有效的 AccountProfile.nickname;非空且不得仅包含空白字符,最多 256 UTF-8 bytes
subject_id string 否 原消息关联对象的标识;含义和格式由 message_type 对应的消息定义确定
subject_name string 否 该关联对象的显示名称,遵循对应对象的名称约束
relay_signature string 是 中继账户对本通知生成的 64-byte Neo N3 签名,无 padding base64url

通知中的消息信息必须与原消息及其记录一致。网关不得仅因未识别 message_type 而拒绝通知。

未取得昵称或昵称为空时省略 sender_nickname。

通知不得包含原消息信封、密文、密钥盒、设备证书或附件内容,也不得通过未知属性携带这些内容。其用途只限提示、展示和导航;接收方不得根据通知推进同步游标、标记消息已读或认定消息内容有效。

签名与认证

签名时只排除根 relay_signature,保留全部其他字段及未知属性,按网络绑定 JSON 输入和中继账户签名规则签署。

网关必须从可信配置取得预期网络和自己的完整公开回调地址,而不是采用请求或未经信任的转发 header 建立预期值。接受通知前必须完成:

  1. 验证 JSON 表示、对象类型、字段、大小和标识格式;账户 network magic 必须匹配预期网络。
  2. 逐字比较 network 与预期网络、push_gateway 与配置的公开接收地址;从预期网络构造签名输入。
  3. 验证公钥与 relay_id 绑定及通知签名;中继公钥、签名表示沿用 RelayDescriptor 的相应字段约束。
  4. 通过预期网络的 Registry 确认中继登记为 active。
  5. 完成网关接受与去重。

网关对通知请求返回成功响应前必须完成上述验证,重复请求也不例外。

网关按上述规则认证发送通知的中继,不要求接收设备对各中继另行授权。

HTTP 回调

发送目标验证

每次发送通知前,按地址来源与更新核对当前网关地址。已签发通知中的 push_gateway 与当前地址不一致时,不得继续发送。

发送前必须确认原消息允许推送、目标设备当前获账户授权且有权访问通知涉及的信息。账户消息的 MessageEnvelope 和群消息的 GroupMessageEnvelope 仅当 notify 为 true 时允许推送。

设备当前授权由其归属中继确认:本中继负责该账户时读取本地当前权威设备状态,否则使用 device.status 的已验证结果;缓存的复用和失效遵循该方法及缓存失效与补查规则。没有可用的已验证授权结果时不得发送。

网关确认

中继向 push_gateway 的完整地址发送不含请求体的 HTTPS OPTIONS 请求,遵循回调连接安全。支持本协议的端点返回:

HTTP/1.1 204 No Content
Meshline-Push: push.notify.v1

只有收到 204 No Content 且 Meshline-Push 响应头的值为 push.notify.v1 时,确认才成功;字段名大小写不敏感,字段值大小写敏感。

中继可复用已取得的确认结果,但当前网关地址必须与确认请求的完整 URL 逐字相同;地址变更后须重新确认。未确认成功时,不得向该地址发送通知。

请求

中继向 push_gateway 的完整地址发送 HTTPS POST,使用 Content-Type: application/json 和 UTF-8 编码的完整 PushNotification,不使用 JSON-RPC 封装。请求体最多 4 KiB(4,096 bytes),计入空白和未知属性。

成功响应

通知请求成功时,网关返回 200 OK、Content-Type: application/json 和结果对象:

{"status":"accepted"}
字段 类型 必需 语义与约束
status string 是 accepted、skipped 或 duplicate,含义如下
状态 含义
accepted 网关已接受本通知,负责后续平台发送和失败处理
skipped 网关已跳过本通知,不向平台发送
duplicate 相同通知已被接受或跳过,本次请求不另行触发处理

三种状态都终止中继重试。accepted 不表示平台已经接受,更不表示设备已经收到、展示或读取通知。

响应可以增加不改变上述含义的扩展属性,接收方忽略这些属性。只有 200 OK 与符合本节定义的结果对象组合才构成成功响应;不满足该条件的 2xx 响应视为结果未知。

错误与发送重试

HTTP 状态 含义
400 Bad Request 格式或字段无效
403 Forbidden 网络、目标地址、签名、身份绑定或已确认的中继资格不符合要求
413 Content Too Large 请求体超过上限
429 Too Many Requests 请求被限流
503 Service Unavailable 接受前临时不可用,例如无法确认 Registry 资格或无法满足去重要求

错误正文可以提供诊断信息。网关接受通知后,不得因后续平台处理失败而返回可重试的 HTTP 错误。

选择重试的中继可以对连接失败、结果未知、408、429 和 5xx 重试;其他 4xx 终止本通知。429 可以提供非负整数秒的 Retry-After;中继重试时必须满足该等待时间,非法值不得按零处理。

重试必须原样复用完整已签名通知。重试前还须执行发送目标验证。

网关接受与去重

去重要求适用于同一网关的单次运行。网关在同一网络、同一接收账户和设备范围内,以 (from, message_id) 判断重复通知。验证通过后,同一通知在去重有效期内只能接受或跳过一次;后续及并发重复请求必须返回 duplicate,不得另行触发处理,即使原通知尚未处理完成。

回调连接安全

每次建立连接时,必须验证最终实际目标为公网可路由单播 IP,拒绝本机、环回、私网、链路本地、多播、未指定及其他非公网地址,包括 IPv4 映射 IPv6 中对应的受限 IPv4 地址。

DNS 解析检查必须与实际连接目标保持一致;不得检查一个地址后再不经检查地重新解析或连接另一个地址。必须验证 TLS 证书与原 URL 主机的绑定,不得关闭证书验证。任何 3xx 都不得跟随,也不根据其中的地址改投。未通过上述验证时不得发送请求。

兼容性与一致性要求

符合本模块的实现必须通过推送通知测试向量,并按一致性测试边界覆盖:

  • 网关声明:证书字段省略及新增、修改、移除,双签名覆盖、设备 ID 稳定、未知字段保留、地址格式与大小;从设备证书取得地址,以及证书更新、会话结束和设备失效时的声明处理规则。
  • 通知报文与认证:字段约束、签名及身份伪造、跨网络隔离和目标地址绑定。
  • 发送目标:消息推送条件、当前设备授权与信息访问权限、地址变更后的目标校验,以及授权结果不可用时禁止发送。
  • 网关确认:空请求体、响应状态与能力响应头、完整 URL 绑定、地址变更后重新确认,以及确认失败时禁止发送通知。
  • HTTP 交互:三种成功结果、错误响应、可选重试、等待时间、原样重试、并发去重、去重范围及不可用时的拒绝。
  • 回调连接安全:受限 IP、DNS 目标切换、TLS 主机验证及重定向。