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

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

离线消息推送测试向量

规范测试向量 · 中继—推送网关协议

覆盖范围

文件:push-notifications-v1.json。固定输入覆盖证书网关声明、设备身份稳定、双签名、发送条件、去重范围、中继签名、未知字段、跨网络隔离、地址格式、网关确认、设备授权查询、证书采用与地址更新、网关去重和 HTTP 处理边界。

这些固定输入不代替推送一致性要求中的网络行为和并发测试。示例地址无需解析或访问。

固定输入与引用

文件根的 network_context 是可信网络上下文,使用通用执行规则;keys 中的私钥只用于测试。signing_algorithm 表示 ECDSA 向量采用 P-256、SHA-256 和 RFC 6979,不额外把 S 转换为低值;协议仍接受数学上有效的高 S 或低 S 签名。

章节 固定输入与预期结果
keys 证书账户、设备和中继测试私钥,中继公钥及 ID,以及接收设备和群的身份派生输入与 ID
device_certificates 无地址、两种不同地址及带未知签名属性的完整证书;设备和账户签名输入、摘要与 DeviceId
certificate_tampering 对完整证书的独立篡改及两次签名的预期验证结果
notifications 完整通知,包含关联对象信息省略、携带非群对象的自定义消息类型和未知签名属性;规范 bytes、签名输入和请求大小
deduplication_keys 改变通知字段或可信网络后,是否仍属于同一去重键;不判断修改后完整通知是否有效
signature_tampering 保留原签名、改变字段或可信网络后的预期中继签名验证结果
gateway_urls 地址格式通过或拒绝用例,包含 query 和 512-byte 边界;不执行 DNS 或网络连接
notification_eligibility 原消息及目标设备的推送条件
gateway_confirmation OPTIONS 请求构造、确认响应判定,以及确认结果与完整 URL 的绑定
device_status 给定当前证书和授权状态时,应返回的授权状态及证书到期时间;网关声明不影响结果
gateway_state 采用证书、认证失败、会话结束、重启及授权变化后的网关地址
deduplication 网关接受、跳过、重复及去重处理不可用场景
notification_responses POST 通知响应对应的中继处理类别
connection_targets 给定实际连接 IP 时的允许或拒绝判断;地址格式通过不能代替此项检查

只展开下表列出的外围同文件 JSON Pointer。展开时移除 _ref 后缀,取得对应完整对象。引用所指对象及签名输入内部的未知属性不作为测试指令。

章节 引用字段 目标
certificate_tampering、device_status、gateway_state[].steps[] certificate_ref device_certificates 中的完整 object
deduplication_keys、signature_tampering notification_ref notifications 中的完整 object

set 和 remove 是测试操作:对原对象作深复制,先删除 remove 列出的根字段,再新增或替换 set 给出的根字段。每项用例独立执行,不改变共享原值;这些测试操作不属于线上协议。candidate_network_context 存在时,只替代本项签名验证或去重判定使用的可信上下文,不自动改写线上 network 字段。

gateway_confirmation.responses 和 notification_responses 使用相同的 response 结构:http_status 为状态码,headers 为响应头,body 为原始正文文本(省略表示空正文);response = null 表示未取得响应。

执行步骤与断言

身份、证书与状态查询

  1. 由 keys 中的私钥独立生成相应公钥;按中继身份规则从公钥派生 relay_id。由 recipient_device_identity 和 group_identity 重建对应 ID,检查结果。
  2. 对每份证书,排除根 device_signature 和 account_signature,注入可信 $context,比对 device_signing_input 中的 Canonical JSON、utf8_hex 和 sha256,验证设备签名。保留设备签名、只排除根账户签名,重建并比对 account_signing_input,验证账户签名和账户绑定。
  3. 独立构造 meshline.device.identity,不得把网关地址或未知属性复制到身份输入。各证书均须得到给定的同一 device_id。
  4. 对 certificate_tampering 应用测试操作,保留原签名,分别验证两次签名;逐项匹配预期失败结果。格式有效或 DeviceId 未变不能代替签名验证。
  5. device_status 用例把指定证书作为当前权威状态的证书,active 直接给出该设备当前授权判定,不使用执行机器的当前时间重新解释这些测试前提。投影 status 和条件 expires_at,与 expected 按字段值及存在性比较;证书中的网关声明不进入查询结果。

原有 identity-auth-v1.json 的无网关证书向量保持原样,并继续按原执行说明验证。

证书采用与地址更新

gateway_state 中每项场景独立开始,中继尚未取得目标设备的网关地址,所有引用证书均属于同一账户下的同一设备 ID。按 steps 顺序执行,每步比较当前记录与 expected_gateway;null 表示没有可用地址。

event 输入与处理
certificate_adopted 已取得并验证 certificate_ref 指向的证书,本步骤采用其网关声明;有 push_gateway 时更新地址,省略时清除地址
device_authentication_failed 携带 certificate_ref 的设备认证失败,未采用该证书,地址记录不变
session_ended reason 给出会话结束原因;地址记录不变
relay_restarted gateway_state_available 给出重启后原地址是否仍可用;不可用时地址记录为空
authorization_checked status = inactive 时清除地址;active 或 unavailable 不修改记录,后者表示未取得可用的授权结果
historical_certificate_read 读取历史证书,但未重新验证并采用,地址记录不变

证书采用顺序由步骤顺序给出,不按证书的新旧排序。重启用例中的地址可用性是测试前提,不规定保存方式。发送前授权检查另按发送目标验证执行。

通知字段与中继签名

notifications 中的每份通知均须通过字段验证,包括未预定义的 message_type 和省略 subject_id、subject_name 的用例。message_type 必须是非空字符串,但不得限定为已知枚举。群消息示例以群作为关联对象;自定义消息示例的 subject_id 为 example-subject-1,不得将关联对象标识统一按群 ID 格式验证。

  1. 从完整通知只排除根 relay_signature,保留全部其他字段与未知属性,注入可信网络上下文,重建 signing_input,比对规范 bytes、摘要和中继签名。按照固定输入与引用中的签名算法说明生成签名时,应精确比对签名字节;其他实现按通用规则比对输入并验证签名。
  2. 对完整通知生成不额外添加空白的 Canonical JSON,其 UTF-8 长度必须等于 request_utf8_bytes。这个值只描述该固定请求表示,HTTP 的 4 KiB 限制仍计入实际发送表示中的空白。
  3. signature_tampering 只测试密码学覆盖:应用操作后,用原公钥和原签名验证,匹配 expected_signature_valid。候选网络替换也必须使验证失败。完整请求的结构、网络和目标绑定检查仍须另外执行。

地址验证

逐项执行 gateway_urls 的地址格式校验,比较 expected_format_valid,不得先改写输入再校验。私网或环回 IP 可以满足 URL 语法,但不能通过实际连接安全检查。

connection_targets 的 address 是已经确定的实际目标 IP;按公网目标限制判断,比较 expected_allowed。这组静态分类不验证 DNS 重新绑定、代理、连接池、TLS 主机验证或重定向阻止,后者必须由独立网络行为测试覆盖。

发送条件与网关确认

notification_eligibility 的 envelope_fields 是已接受信封的字段投影,按发送目标验证比较 expected_allows_push。other_requirements_met 表示其他推送条件是否全部满足;两者均为 true 时,expected_eligible 才为 true。后者只表示推送资格,不要求实际发送。

gateway_confirmation 包含请求构造、响应判定和地址绑定三组独立用例,按网关确认规则执行:

  • requests:以 push_gateway 构造请求,与 expected_request 中的方法、完整 URL 和请求体 UTF-8 字节数比较。
  • responses:按 response 判定确认结果,与 expected_confirmed 比较;存在 expected_follow_redirect 时,还须验证不跟随重定向。
  • bindings:confirmed_url 是已成功确认的完整 URL,null 表示尚未确认;与当前 push_gateway 逐字比较,匹配 expected_applies。该断言只判断确认结果是否适用于当前地址,不代替其他发送目标验证。

实际交互测试还须验证:确认失败时不发送通知;地址变更后先确认新地址;确认请求与通知请求均遵循回调连接安全要求。

网关去重与响应

deduplication_keys 按网关接受与去重规则验证范围隔离:应用字段操作和候选网络上下文后,与原通知在文件根 network_context 下的去重键比较,匹配 expected_same_key。比较范围为网络、to、to_device_id、from 和 message_id,无需派生哈希。部分用例故意使其他字段约束不成立,只检验去重范围,不表示修改后的完整通知可被接受。

deduplication 每个场景从空的去重状态开始。requests 中的整数是 notifications 数组的零起始下标;deduplication_available 给出去重处理是否可用。

固定通知已通过认证检查,场景内所有请求处于同一去重有效期。按顺序处理 requests:去重处理不可用时返回 503;已有同键记录时返回 duplicate;否则采用 initial_decision,记录结果,只有 accepted 触发一次新的处理。

比较 expected_statuses(字符串为成功结果的 status,整数为 HTTP 错误码),并将新增的处理次数与 expected_new_tasks 比较。

notification_responses 按成功响应和错误与发送重试处理 response,比较 expected_action:stop 表示终止本通知重试;unknown 表示未取得成功确认,可以重试;optional_retry 表示允许但不要求重试;do_not_follow 表示禁止根据重定向改投。minimum_delay_seconds 只给出 Retry-After 要求的最低等待,实际重试还须满足发送目标验证。

三种成功状态只确认网关已接受或跳过通知,不能推导平台提交成功或真实设备送达。