主题
模型、枚举与错误
1. 模型命名
原生端公开模型统一以 XHIM 开头。iOS 与 macOS 使用 Swift struct/enum,Android 使用 Kotlin data class/sealed interface,Windows 使用 C# class/record/enum, HarmonyOS 使用 ArkTS interface/class/enum。字段采用各语言惯例:
text
iOS/macOS serverMessageID
Android serverMessageId
Windows ServerMessageId
HarmonyOS serverMessageId同名语义、空值规则和单位保持一致。
2. 生命周期与配置模型
| 类型 | 关键字段 / 用途 |
|---|---|
XHIMEvent | 状态、消息、会话、社交、媒体、Presence 和 Typing 事件联合类型 |
XHIMAccountStateChange | 账号状态、固定剔除原因、revision、account epoch 与连接代次 |
XHIMProjectionChange | durable 本地投影的轻量失效通知 |
XHIMProjectionKind | message upsert/state/local delete、conversation、social、sync |
XHIMProjectionOrigin | local、remoteSync、outbox、未来值 |
XHIMSocialProjectionScope | friend requests、friendships、groups、members、blocks、join requests |
XHIMClientConfiguration | appID、账号存储、事件容量、运行策略、部署发现结果 |
XHIMRuntimePolicy | request timeout、sync page size、reconnect backoff/attempts |
XHIMDeployment | bootstrap URL、Endpoint signing key ID/public key |
XHIMClientMode | production 或仅测试构建允许的 local preview |
XHIMAuthentication | development、accessToken、business provider |
XHIMCompatibilitySnapshot | client/server protocol、最低客户端协议、capabilities |
XHIMDiagnostics | 无敏感信息的容量、队列、请求和回调计数 |
XHIMDeviceSessionPolicy | 多端登录策略、设备上限和当前 session |
3. 消息与会话模型
| 类型 | 关键字段 |
|---|---|
XHIMOutgoingMessage | contentType、contentVersion、payload、fallbackText、deliveryPolicy |
XHIMMessageDeliveryPolicy | durable 或 1 秒到 30 天的 burnAfterRead |
XHIMMessage | local/server identity、sender、state、内容、mutation revision、isLocalOnly |
XHIMLocalMessageResult | changed、deletedCount、localExtension、message、isLocalOnly |
XHIMSendReceipt | SDK 接受操作的 opaque payload |
XHIMMessagePage | messages、nextCursor |
XHIMMessageHistoryContinuation | beforeServerSequence |
XHIMMessageHistoryPage | messages、continuation、latestServerSequence、view |
XHIMMessageSearchQuery | text、conversation、sender、content types、时间范围 |
XHIMMessageVisibility | 当前账号是否删除、revision、mutation ID |
XHIMMessageVisibilityMutation | visibility、idempotent replay |
XHIMConversation | ID、类型/标题、last message、unread、read sequence、revision |
XHIMConversationPage | conversations、nextCursor |
XHIMConversationView | cleared/hidden watermark、revision |
XHIMConversationViewMutation | view、idempotent replay |
XHIMConversationPreference | pinned、notifications muted、服务端规范化 applicationExtensionJSON、可选 messageRetentionSeconds(unknown/null 与权威 0 分离)、revision、mutation ID、updated time |
XHIMConversationDraft | conversation、optional outgoing message、updated time |
XHIMDirectConversation | conversationID、participant user IDs |
XHIMConversationReadReceipt | read sequence、unread count、updated time |
XHIMConversationReadSnapshot | conversation、read server sequence |
XHIMMarkAllConversationsReadResult | changed count、changed reads、truncation flags |
XHIMHideAllConversationsResult | changed count、idempotent replay、Sync projection state |
XHIMConversationPeerRead | reader、read sequence、revision、updated time |
XHIMConversationPeerReadPage | conversation、reads、truncated |
XHIMGroupMessageReadDetail | server message ID、server sequence、reader IDs、派生 read count |
XHIMGroupMessageReadPage | conversation、逐消息 details、peer reads 是否截断 |
XHIMGroupMemberMessageTombstone | conversation、target user、through server sequence、revision、mutation/actor/time |
XHIMGroupMemberMessageModerationResult | 权威 sender-watermark 墓碑和幂等重放标志 |
消息的 payload 始终保持原始不可变字节。未知 contentType 不能丢弃,必须使用 fallbackText 安全降级。
4. 用户、关系链与群组模型
XHIMSocialSummary 使用同一账号加密投影计算有效好友数、收到的 待处理好友申请数、已加入群数和可见的待处理入群申请数,适合直接 驱动通讯录和申请入口角标。
| 类型 | 关键字段 |
|---|---|
XHIMUserProfile | 内部 userID、前端展示 publicUserID、displayName、avatarURL、bio、created/updated time;保持已发布的旧模型前缀,不在其中伪造扩展 |
XHIMUserProfileBatch | profiles、missingUserIDs |
XHIMUserProfileUpdate | 可选 displayName/avatarURL 等更新字段;可选 applicationExtensionJSON 省略不改、空 bytes 清除 |
XHIMUserProfileExtension | 与 profile userID 精确对齐的公开、服务端规范 JSON;空值为权威清除 |
XHIMUserProfileEnvelope | 一份基础 profile + 一份同 ID extension;Native Wrapper 已在回调内深拷贝 |
XHIMUserProfileBatchWithExtensions | profiles、等长/同下标 extensions、missing user IDs |
XHIMFriendRequest | 基础 requestID、from/to、introduction、source、sourceConversationID、state、revision;旧 Core 兼容模型不表示扩展可用性 |
XHIMSocialRequestExtension / XHIMFriendRequestEnvelope | 与好友申请 requestID 精确对齐的参与双方可见扩展 |
XHIMFriendship | peer profile/remark、当前账号私有置顶、受限业务扩展 JSON、共享属性 CAS revision、created/updated time |
XHIMFriendRequestResolution / extension-aware variant | request、可选 friendship;扩展感知结果另返回原申请的权威扩展 |
XHIMFriendshipDeletion | peer、deleted、idempotent replay |
XHIMFriendRemarkChange | peer、remark、revision、idempotent replay |
XHIMRelationshipStatus | userID、isFriend、blockedByMe |
XHIMGroup | conversationID、title、avatar、owner、member count、memberProfileVisible、memberFriendRequestsAllowed、newMemberHistoryVisible、群公开业务扩展、revision |
XHIMGroupMember | group、user、群内 nickname、实时 displayName/avatarURL、成员级 applicationExtensionJSON、role、state、mute、revision |
XHIMGroupJoinRequest / extension-aware variant | request、group、applicant、state、revision;扩展感知结果携带只对申请人与管理者可见的审批 metadata |
XHIMGroupChange | group、revision、changed member count、idempotent replay |
XHIMGroupLifecycleResult | group、left/dismissed、idempotent replay |
XHIMGroupJoinMutation | request、membership result、idempotent replay |
XHIMBlock / extension-aware variant | blocked user、active、revision、updated time;扩展感知结果携带当前账号私有的方向扩展 |
XHIMSocialPage<T> | items、nextCursor、可选 group revision fence |
XHIMSocialProjectionIntegrity | kind/reason、complete、marker/revision/count/checkpoint/scope,用于证明加密本地群投影完整性 |
applicationExtensionJSON 在用户资料上是对陌生人也可见的公开业务 元数据,不受 privateProfileVisible 隐藏。它只能容纳非敏感、非认证、 非凭证的小型 JSON object。好友申请扩展只对申请双方可见; 入群申请扩展只对申请人和群主/管理员可见;黑名单扩展只对 当前账号可见;群扩展对可读取群资料的成员可见。
扩展可用性和扩展值必须分开:
- 旧/基础模型没有扩展字段,或 Android 兼容模型中为
null, 都表示 unknown/unavailable; - 扩展感知方法成功后的空
Data/空字符串表示服务端 authoritative clear; - 非空值是服务端 canonical JSON,不保证与请求原文字节相同。
Apple、Android、Windows 的基础关系模型使用 nullable applicationExtensionJSON/Json 表达 unknown;显式 extension-aware 入口 成功后保证该字段 non-null。HarmonyOS 用独立强类型 extension-aware 模型;Flutter 保留 Dart nullable 表达能力不可用;Electron 基础模型字段 可缺失,显式结果则是 required string。Web 直接服务端 Facade 的扩展 字段是 canonical 权威值。
5. Presence、Typing、Push 和设备
| 类型 | 关键字段 |
|---|---|
XHIMPresenceUpdate | eventID、userID、status、activePlatforms、sequence、expiresAt |
XHIMPresenceSnapshot / XHIMPresencePublication | 授权查询或服务端接受后的 Presence 快照 |
XHIMTypingUpdate | eventID、conversationID、userID、isTyping、activePlatforms、sequence、expiresAt |
XHIMTypingSnapshot / XHIMTypingPublication | 纯读或发布后的 Typing 快照;纯读可返回 sequence 0 |
XHIMCustomSignal | event/conversation/sender/client signal ID、content type/version、payload、sequence、expiresAt |
XHIMPushDevice | platform、deviceID、秘密 token、environment、locale |
XHIMPushDeviceRegistration | enabled、token reassigned、device limit/evictions |
XHIMPushDeviceDisableResult | disabled、changed |
XHIMDeviceSession | session/device/platform、current/active、时间、revoke reason |
XHIMDeviceSessionPage | sessions、policy |
XHIMDeviceSessionRevocation | session、revoked、idempotent replay |
Push Token 的 description/debug output 会被替换为 <redacted>。
6. Call Session 与 RTC 凭证
| 类型 | 关键字段 / 用途 |
|---|---|
XHIMCallMediaKind | audio、video、未来值 |
XHIMCallSessionState | ringing、active、ended(终态)、未来值 |
XHIMCallSignalKind | invite、accepted、rejected、ended、未来值 |
XHIMCallSession | call/conversation/inviter/participants、media/state、sequence、时间和结束原因 |
XHIMRTCCredentialLease | provider、room、短期 token/endpoint、expiresAt;禁止持久化和日志 |
XHIMCallAcceptResult | active session 与一次短期 RTC credential lease |
XHIMCallSignal | durable offset、per-call sequence、actor、participants、state 及可选短期凭证 |
XHIMCallSignalPage | signals、recovery active sessions、next offset、hasMore、server time |
Call 的数据顺序和凭证安全合同见 Call Session、RTC Provider 与崩溃恢复。
7. 媒体模型
| 类型 | 用途 |
|---|---|
XHIMMediaEncryption | scheme、keyID、nonce、wrappedKey |
XHIMMediaRef | 不可变服务端媒体身份和内容哈希 |
XHIMMediaTask | durable upload/download 状态快照 |
XHIMMediaTaskUpdate | 轻量事件载荷;用 taskID 重查完整任务 |
XHIMMediaUploadIntent | 本地上传文件和依赖消息元数据 |
XHIMMediaDownloadIntent | media ref、cache key 和下载目的 |
XHIMMediaUploadRequest | 兼容旧 uploader 的直接上传请求 |
XHIMMediaUploadProgress | phase、completed bytes、total bytes |
XHIMMediaCacheReader | SDK 缓存对象的有界读取句柄 |
XHIMMediaMessageContent | 图片、视频、语音、文件消息的强类型接收端内容 |
XHIMMediaDownloadProgress | 授权/下载/校验阶段和字节进度 |
XHIMDownloadedMedia | 已完成大小与 SHA-256 校验的私有缓存文件 |
XHIMLocationContent | 标准位置消息的经纬度、名称与地址 |
XHIMContactCardContent | 标准名片消息的内部路由 ID、昵称与头像;UI 不直接展示内部 ID |
Android/HarmonyOS 在文件或 URI 模型上使用平台原生类型,但进入 Core 后语义 相同。
XHIMSDKMetadata
进程内 SDK 构建身份:version、sourceCommit、abiVersion。 该类型不含运行时会话数据,可用于客服工单、崩溃元数据和制品验收; 不应将其与 Server XHIMCompatibilitySnapshot 混淆。Web 端的 abiVersion 为 null,并额外标注 metadataSource=package-build。
8. 自定义消息模型
| 类型 | 用途 |
|---|---|
XHIMMessagePlugin / IXHIMMessagePlugin | 版本校验与展示适配协议 |
XHIMMessagePluginRegistry | 注册、反注册、校验和 presentation 查询 |
XHIMMessagePresentation | conversation preview、notification preview、renderer key |
XHIMMentionContent | 标准 @ 消息解码结果 |
XHIMForwardItem | 合并转发中一个不可变消息条目 |
XHIMQuoteContent | 引用回复的源消息 ID、发送者、摘要和回复正文 |
XHIMMergedForwardContent | 合并转发标题和最多 100 个不可变消息条目 |
9. 主要枚举值
XHIMClientState
| 值 | 含义 |
|---|---|
created | 已创建,Core 未启动 |
started | Core 已启动,未登录 |
authenticating | 正在认证 |
connecting | 正在建立实时连接 |
synchronizing | 正在同步本地投影 |
ready | 可读写 |
credentialRequired | 需要续凭 |
loggingOut | 正在退出 |
closed | 已不可逆关闭 |
fatal | 不可恢复错误 |
XHIMAccountState 与 XHIMKickedReason
XHIMAccountState:unknown(0)、active(1)、suspended(2)、unregistered(3);XHIMKickedReason:none(0)、accountSuspended(1)、accountUnregistered(2)以及各平台的未知值保留形式。
XHIMAccountStateChange.revision > 0 才是服务端权威版本;0 是旧实时 frame 没有 tag 19 的兼容值。强类型事件不包含管理员填写 的治理原因。对 suspended / unregistered 客户端只依赖 account_suspended / account_unregistered 这两个固定 stable code。
XHIMMessageState
pending、sending、retrying、serverAccepted、failed、cancelled, 以及平台用于前向兼容的 unknown。
XHIMMessageContentKind
text(1)、image(2)、audio(3)、video(4)、file(5)、 custom(1000)、unknown。业务判断优先使用 contentType,不要只依赖这个旧式 粗粒度 kind。
XHIMMarkdownContent
text/markdown@1 的强类型解码结果,包含 source 和 plainTextFallback。两者都必须是非空、无 NUL 且不超过 64 KiB UTF-8 的 文本。该模型不代表已净化 HTML;SDK 不负责渲染,宿主必须使用安全 Markdown Renderer,无法渲染时显示 fallback。
XHIMMessageMutationKind
none、editText、recall、unknown。
XHIMMediaTaskState
pending、authorizing、transferring、paused、verifying、 completed、failed、cancelled、unknown。
XHIMMediaTaskDirection:upload、download、unknown。
Projection 与短暂状态
XHIMProjectionKind:messageUpserted、messageStateChanged、 conversationChanged、socialChanged、syncApplied、unknown;XHIMProjectionOrigin:local、remoteSync、outbox、unknown;C ABI 也保留 realtime 原始值供未来 Facade 使用;XHIMSocialProjectionScope:none、friendRequests、friendships、groups、 groupMembers、blocks、groupJoinRequests、unknown;XHIMPresenceStatus:online、away、offline、unknown。
Presence 主动查询快照和 presenceChanged 实时事件的 activePlatforms 是同一份 protobuf repeated enum。参考 Server Product Adapter 必须同时接受 protobuf 标准的 packed 编码和历史 unpacked 编码,并对数量及枚举范围做边界校验。应用层不解析 WebSocket 原始字节,只消费 SDK 给出的类型化在线端列表。
关系链与群组
XHIMFriendRequestState:pending、accepted、rejected、unknown;XHIMFriendRequestDecision:accept、reject;XHIMFriendRequestSource:profile、card、phone、account、qrCode、group;XHIMGroupMemberRole:owner、administrator、member、unknown;XHIMGroupMemberState:joined、removed、unknown;XHIMGroupJoinRequestState:pending、accepted、rejected、unknown;XHIMGroupJoinDecision:accept、reject;XHIMGroupGovernanceChange:setAdministrator、setMute、setAllMute、 transferOwnership、setJoinApprovalRequired、setProfile、setOwnNickname、 setAccessPolicy、setNewMemberHistoryVisible、setMemberApplicationExtension、 setApplicationExtension;XHIMSocialProjectionIntegrityKind:joinedGroups、groupMembers、unknown;XHIMSocialProjectionIntegrityReason:complete、markerMissing、 replayIncomplete、checkpointMismatch、revisionMismatch、 memberCountMismatch、ownerMismatch、unknown;XHIMMultiLoginPolicy:由服务端 capability snapshot 给出稳定策略名。
Flutter Facade 为了保持 Alpha 期存量代码兼容,仍保留原始 state / role 数值,同时提供 resolvedState / resolvedRole 强类型访问器。UI 和二次开发 应使用强类型访问器,不要在页面里散落 1 / 2 / 3 数字判断。
XHIMPushPlatform
apns(1)、fcm(2)、huawei(3)、web(4)。
XHIMDevicePlatform:iOS、Android、macOS、Windows、HarmonyOS、Web、Linux 和 unknown。
XHIMUserAction
none、retry、updateCredential、checkNetwork、contactSupport。
10. 稳定错误模型
iOS/macOS/HarmonyOS 暴露 XHIMNativeError,Android/Windows 暴露 XHIMException。业务分支使用这些字段:
| 字段 | 稳定性 | 用途 |
|---|---|---|
code | ABI 稳定 | 粗粒度状态 |
domain + stableCode | 跨语言稳定 | 推荐的业务判断键 |
nativeCode | 透传 | HTTP、系统或服务端原始码 |
retryable | 稳定 | 是否允许自动/手动重试 |
retryAfterMilliseconds | 稳定 | 最早重试等待 |
userAction | 稳定 | UI 建议动作 |
operationID + traceID | 稳定诊断 | 服务端链路排查 |
message | 不稳定文本 | 仅日志和开发提示,禁止业务字符串匹配 |
Reference Server 返回非 2xx 时,Apple 与 Reference Product Adapter 会严格解析 服务端 ErrorEnvelope,保留 code、可读 message、retryable 和 retry_after。Envelope 非法、字段重复、超长或不是 UTF-8 时安全降级为通用 后端错误,不能把未经验证的服务端字节直接显示给用户。UI 至少展示 stableCode + message;不应只把 ABI 数值显示成“错误 1”。
消息撤回需要区分两个业务错误:forbidden 表示当前用户没有撤回该消息的权限; recall_window_expired 表示消息属于当前用户,但已超过服务端允许的撤回窗口。 两者都不应自动重试,客户端分别展示“只能撤回自己发送的消息”和“已超过撤回时间”。
ABI code:
| 数值 | 名称 | 常见处理 |
|---|---|---|
| 0 | OK | 成功 |
| 1 | INVALID_ARGUMENT | 修正调用参数,不重试 |
| 2 | INVALID_STATE | 等待 ready 或修正生命周期 |
| 3 | NOT_INITIALIZED | 先 start/connect |
| 4 | ALREADY_CLOSED | 新建 Client |
| 5 | BACKEND_NOT_CONFIGURED | 当前发行包缺少 Product Adapter |
| 100 | STORAGE_ERROR | 检查空间/数据库 Key,必要时联系支持 |
| 101 | IDEMPOTENCY_CONFLICT | 重查实体,不盲目换 mutation ID |
| 102 | NOT_FOUND | 刷新列表或提示对象不存在 |
| 103 | UNSUPPORTED | 检查 capability/version |
| 104 | FORBIDDEN | 按服务端权限提示 |
| 105 | ACCOUNT_SUSPENDED | 停止续凭/重试,销毁当前账号容器并回到登录 |
| 106 | ACCOUNT_UNREGISTERED | 停止续凭/重试,清理登录态;账号不可恢复 |
| 200 | CANCELLED | 调用被取消 |
| 201 | SDK_SHUTDOWN | Client 正在/已经关闭 |
| 202 | CALLBACK_QUEUE_FULL | 降低请求洪峰并收集诊断 |
| 203 | CREDENTIAL_REQUIRED | 由账号层 Provider 续凭 |
| 900 | INTERNAL_ERROR | 记录 operation/trace ID 并联系支持 |
application-extension 便利入口在加载旧 Core 时使用 103 UNSUPPORTED fail-closed;不得抓住该错误后回退基础写入入口。 新 Core 与未声明对应 extension capability 的旧 Server 组合也使用 103 在 mutation 前 fail-closed;符号存在不代表服务能力已协商。 基础列表仍可成功,但其扩展状态是 unknown。群成员完整投影刷新中 group_member_projection_revision_stale 是可重试的 revision 竞态; complete=false + 强类型 reason 是成功检查结果,不是错误。
105/106 的 retryable 固定为 false,stableCode 分别固定为 account_suspended / account_unregistered。Facade 不显示或转发服务端 管理厘由,也不得将这两类错误交给凭证 Provider 自动续凭。恢复 停用账号也不会恢复旧 Token,必须重新走购买方身份认证。
推荐处理:
swift
catch let error as XHIMNativeError {
switch (error.domain, error.stableCode, error.userAction) {
case (_, _, .updateCredential):
accountSession.requireLogin()
case (_, _, .checkNetwork):
banner.showOffline()
default:
logger.error("XHIM \(error.operationID) \(error.traceID)")
}
}11. 一键连接错误
一键连接异常专用于 Server URL 验证、公开发现和首个凭证获取:iOS、macOS 和 HarmonyOS 为 XHIMConnectionError,Android 为 XHIMConnectionException, Windows 为 XHIMConnectionException。其错误类别包括:
- invalid server URL / identity / server configuration;
- insecure transport not allowed;
- development login disabled;
- credential unavailable;
- server rejected(含 HTTP status);
- response too large。
它发生在 Client 完全建立之前,与运行期 XHIMNativeError 分开处理。