摘要

  • draft-ietf-calext-vcard4-bis-00 对 UID 等价、PID 等价和若干属性匹配给出强制规则,也明确把其他同名属性的合并留给同步引擎判断。
  • 同步后的 vCard 是当前状态的收据,不是完整决策历史。传输认证、记录匹配、属性合并、冲突处理、来源压缩和实际正确性必须分别留证。

一条 MUST 解决的是记录归并,不是人的身份

两台设备曾经共享过同一张联系人名片,之后各自在离线状态下修改。下一次相遇时,系统首先要回答:这是不是同一条记录的两个版本?

修订版 00 给出一条强规则:UID 等价的 vCard 实例必须匹配。有效 URI 按 RFC 3986 判断等价;其他情况在去除 vCard 文本转义后逐字符比较。规则让系统不必仅凭姓名、号码或邮件地址猜测,也避免每次导入都制造一个新联系人。

但“记录必须匹配”不是“现实人物已经核验”。相同 UID 可能被正确继承,也可能被错误复制、恶意复用或从一开始就绑定错对象。发送者可能有权更新办公电话,却无权覆盖紧急联系人。两份记录可以确实来自同一张名片,却包含不同时间、不同来源和不同可信度的字段。

UID 在同步算法内部拥有明确权威:它决定哪些记录必须进入同一场归并。它没有从格式之外取得身份证明、授权或字段真实性。把前者扩张成后者,正是基础设施系统最常见的权力错位。

修订版 00 仍是工作文件

《vCard Format Specification》修订版 00 发布于 2026 年 7 月 2 日,2027 年 1 月 3 日到期,属于 CALENDAR EXTENSIONS 工作组并以 Standards Track 为目标;若获批准,它将取代 RFC 6350。当前它仍是 Internet-Draft,不是 RFC,也不是任何产品已经一致实现的证明。

它解决的问题非常现实。联系人并不只有姓名和电话号码,还可能包含地址、机构、角色、照片、密钥、日历入口与关系。独立软件若没有共同语法与 IANA 注册表,只能靠私有字段互相猜测。

共同格式是真实基础设施。问题不是格式“只是文书”,而是要求它承担未设计的职责。docs/heng-lu-note.md 中 Running-Code Primacy 的约束在此十分清楚:文档发布、代码实现、输入验证、同步执行、用户采用和现实结果,是不同事件。共同文本可以协调这些事件,不能替代它们。

Minimum Initial Specification 也给出同样方向:把必须共同理解的最小结构写清楚,把未来的情境判断保留给本地执行者。保留判断并不等于免除责任;谁执行本地判断,谁就需要为判断留下收据。

UID 不是每张名片都必须具备的现实锚点

UID 的基数是 *1,表示最多一个,而不是必有一个。UID 不等价或缺失时,同步引擎仍可以自行判断两张名片是否代表同一对象。

这条设计承认现实数据并不整齐。旧系统可能没有 UID,文本 UID 可能使用非 URI 形式,导入链路也可能丢失字段。完全禁止启发式匹配会留下大量重复记录。

风险在于启发式匹配往往依据姓名、邮件、电话或机构相似度。这些字段会重名、复用、变更,也可能属于共享岗位。一个把“王伟 + 同一公司”判作同一人的模型,也许在多数情况下节省人工,却可能把两个人的敏感字段永久合并。

因此,UID 强制匹配和无 UID 启发式匹配必须分别统计。前者记录 UID 等价证据,后者记录输入字段、归一化、规则或模型版本、置信度、阈值和审核人。最终记录只显示系统相信什么,不能倒推出系统为什么相信。

PID 解决属性身份,不解决属性权利

记录匹配后,还要判断多个同名属性是否对应。一个联系人可以有多个 EMAIL、TEL 或 ADR。仅比较可见值不够:号码格式可能改变,地址可能更新,两个来源也可能独立录入同一个值。

PID 的第一个字段是属性的本地值编号。第二个字段是来源编号,这个小整数只在当前 vCard 实例内有意义。CLIENTPIDMAP 再把来源编号映射到 URI,让本地编号获得可跨实例比较的全局语境。

每个被 PID 使用的来源编号都必须有对应映射,编号必须为正,零不允许。若本地值编号相同,且来源编号经映射后得到等价 URI,两个 PID 就可以代表同一个全局属性值。

这种间接层避免把简单整数误当全局唯一值。设备 A 与设备 B 都可使用来源 1,各自的 CLIENTPIDMAP 负责区分。

但 CLIENTPIDMAP 不是签名。一个 UUID 形态的 URI 只是名称,不能证明命名设备实际创建了字段,也不能证明该设备获准覆盖另一个来源。它提供身份关联,不提供保管链。授权、认证与来源真实性仍在格式之外。

强制规则先圈出不可任意决定的部分

修订版 00 并没有把所有事情都交给“智能”。未匹配名片的属性不得互相匹配;名称不同的属性不得匹配;已匹配名片中,同名且最大基数为一的属性必须匹配;同名且 PID 匹配的属性也必须匹配。

这些规则构成安全栏。TEL 不能因字符串相似而变成 EMAIL,另一个人的属性不能被拖入当前联系人,已有稳定 PID 关系也不能因为厂商偏好而被忽略。

剩余的同名属性则可以由同步引擎自行匹配。这里的 MAY 是明确的权力交接:标准不可能统一判断所有号码写法、姓名变体、地址归一化和用户意图。

权力交接必须伴随责任交接。引擎应记录它比较了什么、做了哪些归一化、使用哪个规则版本、为什么超过阈值、保留或删除了哪些备选值。IETF 允许做决定,不等于 IETF 替部署者做了决定。

同时编辑的例子暴露了算法权力

草案的例子让两台设备分别添加一个新邮件地址和一个新电话号码。由于来源上下文不同,新增属性拥有不同的全局 PID。

两个邮件地址因此不匹配,最终都被保留。两个电话号码的 PID 也不匹配,但可见号码相同。例子假设一个“特别聪明”的引擎识别出它们应是同一个属性,于是将两者合并,并在最终 TEL 上保留两个 PID。

这可能完全正确。也可能遗漏未编码语境:一个是工作值,一个是值班入口;一个经过人工确认,另一个来自旧导入;一个系统把分机当独立字段,另一个在归一化时丢掉了分机。

最终 TEL 上的双 PID 证明两条属性身份已经汇合,却不能证明汇合理由。部署者需要另一份决策收据:原始属性哈希、原始 PID 和映射、归一化前后值、匹配规则、置信度、策略结果、操作主体与时间。如果人工确认,应单独记录人工确认,不能与模型建议混为一条事实。

CLIENTPIDMAP 冲突是停止确定性的信号

CLIENTPIDMAP 不像普通属性那样互相匹配。同步引擎必须保证已匹配名片之间的映射一致。若不一致,草案例子明确说结果由同步引擎决定,本文档不予定义。

不一致可能来自合法重编号、过期副本、碰撞、损坏或来源替换攻击。不同信任架构很难共享一条普遍安全的自动规则。

“标准未定义”不应被解释成“产品可以无声覆盖”。安全实现至少应保留冲突输入、停止不可逆处理、输出原因码并调用本地策略。个人通讯录可以提示用户;企业目录可以隔离;有签名历史的系统可以查验保管链。

若产品直接覆盖一张映射表,随后以“符合 vCard”解释结果,它是在用格式合规掩盖本地权力。

全局语境简化让状态更短,也让历史更难恢复

同步完成后,例子进一步简化全局语境。由于只有两台设备参与,它把属性重新编号,删除一个来源上下文,使最终 vCard 更短。

草案明确说明,简化细节并未规范,示例只是展示一种值得研究的可能性。因此,不同引擎可能在都声称等价的情况下产生不同投影。

压缩不是错误。分布式系统需要快照、垃圾回收与物化视图。把完整事件历史塞进每张可移植联系人会使格式臃肿。

正确边界是:服务使用紧凑 vCard,审计系统保存长收据。简化前记录输入对象哈希、来源映射、冲突决定和旧编号;简化时记录旧到新变换;简化后记录输出哈希。前者回答现在提供什么,后者回答为何变成这样。

如果只剩压缩后的名片,它可以证明当前状态,不能证明完整因果。

安全传输不能替语义合并背书

草案提醒,vCard 本身不提供认证或保密,可由 S/MIME 等机制保护。CardDAV 的 ETag 可以标识资源版本,WebDAV 同步令牌可以枚举集合变化。

这些都是必要收据,却回答不同问题。认证信封证明特定凭据在某个信任配置下发送了完整字节;ETag 证明客户端针对哪个存储版本;同步令牌证明从某个时点起哪些资源发生变化。

它们都不能决定两个号码是否应合并。通过认证的发送者也可能没有权力修改全部字段。正确命中版本的写入也可能包含错误的语义判断。完整列出变化资源,也不会解释某个邮件地址为何消失。

审计链需要分别记录传输主体、授权结果、版本、名片匹配依据、强制属性匹配、启发式属性匹配、冲突策略、存储投影和实际结果。

SOURCE 与 REV 只能提供粗粒度线索

SOURCE 可指出资料来源,REV 可表示名片最后更新时间。这些字段有助于缓解信息过期,却不是每个属性的来源账本。

同一张名片可能混合企业目录邮件、用户手填手机与外部导入的紧急联系人。一个 SOURCE 无法表达全部来源,一个 REV 也无法表达每个字段的年龄,更不能记录某次合并的授权。

这不是要求 vCard 变成事件存储协议。相反,应让可移植格式保持小而清晰,由承担敏感合并的应用保存更丰富证据。影响越大,收据越完整。

真正要监控的是决定,而不只是收敛率

许多同步系统把“最终一致”当成成功率。两台设备最后显示相同名片,便宣布任务完成。

对运营者而言,还要问:多少名片由 UID 强制匹配,多少靠启发式;多少属性由 PID 强制匹配,多少由模型决定;多少 CLIENTPIDMAP 冲突;多少自动合并后来被用户拆分;多少字段被删除;多少简化操作缺少变换表;多少同步成功后发生拨错、退信或错误授权。

收敛率衡量系统是否达成同一状态。它不衡量状态是否正确,也不衡量决定能否解释。

vCard4-bis 最有价值的地方,正是它没有假装格式可以回答所有问题。UID、PID 与禁止规则拥有明确边界;剩余判断回到本地。

运营原则因此很简单:让 UID 决定记录边界,让 PID 决定已知属性边界;凡是启发式跨过的边界,都留下决策收据。可以压缩名片,不要同时压缩问责。

Sources