主题
可信业务通知消息合同
1. 消息信封
Core 识别精确类型 application/vnd.xhim.business-notification+json 和 version 1。payload 必须与 服务端 Go encoding/json 产生的 canonical 字节完全一致:
json
{
"schema_version": 1,
"visibility": "server_visible",
"encrypted": false,
"title": "系统维护",
"body": "今晚 23:00 开始",
"data": {"ticket_id": "maintenance-1"}
}上面为易读展示;线上字节不含缩进和多余空白,顶层字段顺序固定。 data 可省略,但出现时必须是 canonical JSON object。边界为:
- payload 最多 64 KiB;
- title 最多 512 UTF-8 字节,不得包含 NUL,且必须已等于 Go
strings.TrimSpace后的值; - body 最多 48 KiB,不得包含 NUL,且不能只有 Unicode 空白;
- data canonical 字节最多 48 KiB,最深 64 层,对象键按 Go UTF-8 字符串顺序排列,重复键拒绝;
- 字符串遵循 Go JSON 转义:
<>&、U+2028 和 U+2029 必须转义; 数字保留json.Number的有效词法,包括-0、指数和超大整数。
Go 生成器为 scripts/dev/generate_business_notification_golden.go, 跨语言固定向量为 compatibility/protocol-golden/business_notification_v1.tsv。
2. 失败安全与本地历史
typed parser 是一个可选展示投影,不是 Sync 接纳条件。未来 version、 未知字段、重复键、非 canonical 转义、超限或恶意 payload 仍按 content_type + content_version + payload + fallback_text 原样写入 SQLite/历史/同步。它们只有 typed projection unavailable,不能导致消息丢失。
Reference Product Adapter 和 Apple Product Adapter 共用同一个 generic ServerCodec::decode_sync;该 codec 对通知无专用分支,并原样保留 content type、version、payload 和 fallback。
3. UserProfile 类型投影
服务端账号类型为 human | notification_service。 xhim_social_v1.proto.UserProfile.user_type = 17 是 additive 权威字段: UNSPECIFIED=0 表示旧服务端、旧缓存或当前 SDK 不识别的值, HUMAN=1,NOTIFICATION_SERVICE=2。Core 保留未来非负 raw value; SQLite v34 迁移对 v33 行填 UNKNOWN=0,等后续服务端权威 profile 覆盖,绝不把旧行猜成 human。
C ABI 在不改变 xhim_v1_user_profile_snapshot_t 224 字节大小和数组 stride 的前提下,将尾部 reserved_profile_u32 复用为 int32_t user_type。 不往 application_extension_json 塞私有字段,也不根据 user ID 前缀推断。