一致性向量¶
向量是规范的组成部分:绝大多数是 hash 契约 1 的向量,config_schema_patterns.json 是 connector 契约 §4.1.1(config_schema 的正则子集)的向量,nesting_depth.json 是 core.md §2.8(对象嵌套深度上界)的向量,两者与 hash 契约无关。全部由规范参考实现 scripts/gen_vectors.py(辅以 scripts/pattern_subset.py)生成;SDK 与任何服务端实现只消费向量(在各自 CI 中逐字节校验),不得生成或手改。
文件格式¶
每个 *.json 是一个向量,kind 六类:
document:documents是一到多篇文档的 hash 输入:- 文档:
file_type、可选title、可选doc_metadata、pages[{title, page_metadata, elements[]}];页没有页号,数组顺序即阅读顺序。 - 元素:元素对象,即 category 允许的字段加
metadata。 - 这是三层对象的展开视图:线上的文档对象
pages与页对象elements是子对象 hash 列表,子对象单独投递(契约 1 §5)。
- 文档:
expected给出每篇文档在各契约下的doc_hash、逐页的page_hash,以及逐元素的content_hash(pages[i].elements[j],i 为输入数组下标)。preimage_basic另给出preimages:文档对象(document)、各页对象(pages)、各元素对象(elements)规范化后的 JCS 原像字符串,hash 即其 UTF-8 字节的 SHA-256。relations(可选)是本向量要证明的规范性质,生成器在生成时断言其成立,消费方 SHOULD 一并断言:{"equal": [ref…]}:所列值两两相等;{"distinct": [ref…]}:所列值两两不同。ref形如<文档键>.<路径>,例如base.doc_hash、base.pages.0.page_hash、base.pages.0.elements.1;有多个契约时,在每个契约下分别成立。
jcs:cases[]每条给出 JSON 输入、RFC 8785 规范化字符串canonical及其 UTF-8 字节的sha256。uri:file_uri 的语法规范化(core.md §1.1)。cases[]每条给出合法输入input与其规范化输出normalized(规范化幂等,normalized是不动点);invalid_cases[]每条给出必须被拒绝的输入input与期望错误码code(恒为DPE_VALIDATION)。消费方 MUST 逐例通过。invalid:拒绝类用例,固定 core.md §2.8 的校验顺序。cases[]每条包含:object_kind:element/page/document(线上原像),或expanded_document(上文的展开视图,按与线上请求相同的顺序校验:文档自身字段 → 各页自身字段 → 各页元素);contract:本次选择的契约;input:被校验的 JSON 值;或改为input_json,以原始 JSON 文本给出,用于 I-JSON 违例这类无法以解析后的值表达的输入。消费方 MUST 用拒绝重复键的严格解析器读取,解析阶段的拒绝同样视为DPE_VALIDATION,位置为""(core §2.8 第 0 步);code:期望的错误码;path(可选):期望的违例位置,RFC 6901 JSON Pointer。
消费方 MUST 拒绝每条输入,且错误码一致。用例带 path 时(只有一处违例的输入),违例位置也 MUST 一致。不带 path 的用例含多处违例,只断言错误码,以此检验校验顺序。生成器在生成时用参考校验器断言每条用例。
「受支持的契约」按 manifest 的 contract 加上用例的 contract 计算,不按消费方自己支持的契约集合计算。例如,同时支持 dpe1 与 dpe2 的过渡期服务端仍应按此口径运行用例。(运行时校验按服务端声明的契约集合判定,core.md §3.1;此处口径只用于运行向量。)
nesting_depth(nesting_depth.json,规范依据 core.md §2.8 第 0 步第三项):limit:对象的嵌套深度上界(MUST ≤limit,超出为DPE_VALIDATION);实现导出的常量 MUST 与之相等;cases[]每条包含object_kind、contract、input(被校验的 JSON 值)与input_json(同一输入的 JSON 文本)。accept: true的用例 MUST 被接受;其余给出code(单处违例的用例还给出path)MUST 被拒绝且错误码一致。消费方 MUST 对每条用例走两条路径并得到同一结论:对象级入口(直接校验input)与文本入口(严格解析input_json后校验)。边界用例的最深一层是空容器({}或[]);- 深度按每个对象自身计:标量记 0,对象或数组记 1 + 其子值的最大深度,空容器记 1(
{}记 1、{"a": {"b": [1]}}记 3);页的elements与文档的pages按子 hash 列表计(列表自身记 1、每一项不计入),深度与对象在报文中的位置无关(绑定信封的层数不计入); expanded_document用例的违例位置同样为对象自身(""),不换算为相对报文根的路径(core §2.8 违例位置)。pattern(config_schema_patterns.json,规范依据 connector 契约 §4.1.1,与 hash 契约无关):valid_patterns[]:MUST 被接受且可转译(子集外的 pattern 使清单整体manifest_invalid);匹配语义由match_cases逐条钉住;含结构上界边界与最坏情况形状;invalid_patterns[]:MUST 被拒绝;reason是参考实现给出的原因标记,供人阅读,不作跨实现的断言。无法以普通字符串表达的输入(孤立代理项等,同 hash 向量的input_json约定)以pattern_json给出原始 JSON 文本,消费方用严格解析器读取;match_cases[]:每条给出pattern、value与是否匹配的match;无法以普通字符串表达的输入(孤立代理项等)以value_json给出原始 JSON 文本(同pattern_json的约定)。期望值是手写的规范语义,生成器只用参考匹配器交叉核对(不一致即生成失败),避免「翻译器自己验证自己」;消费方 MUST 逐条通过;schema_cases[]:每条给出schema(必填)与manifest_valid(必填);可另给config与config_valid(两者必须成对出现,生成器断言其配对)。manifest_valid由 §4.1.1 的封闭关键字子集检查器交叉核对(未列出的关键字、$defs非根、$ref非唯一形式(含前缀/解码边界)/目标不存在/$defs引用成环、items数组形式、schema 的展开深度(≤64:根计 1,schema 位置与$ref跳转各 +1、沿引用继续计)、清单文件的 JSON 嵌套深度(≤64;向量里的schema被包进清单对象,计数含包装层,含数据位置上的深度)、容器形状与type取值,以及 pattern 子集越界都判清单不合法;const/default/examples内的同名键是数据);config_valid是手写期望,生成器不做 JSON Schema 求值。
manifest.json 记录:
- 契约版本;
- 契约常量,与 SDK 导出的常量必须一致:file_type 推荐登记表 file_types(按 core.md §2.5 表中顺序),以及 category 封闭枚举与各自允许的内容字段 category_content_fields(契约 1 §4.1;键按名排序,字段按表中顺序);
- 生成器与各文件的 sha256(provenance)。
假想契约 dpe2¶
upgrade_drill.json 用于契约升级演练(同一份内容在两个契约下的期望值)。dpe2 不是真实契约,仅用于测试,定义:与 dpe1 完全相同,但每个对象的摘要输入是 ASCII dpe2 后接 JCS 原像字节,即 sha256(utf8("dpe2") ‖ utf8(JCS(norm(obj)))),值前缀为 dpe2:。实现的多契约管线应能同时算出两者;两契约 expected 中逐页、逐元素结果按位置一一对应,即契约升级"原位重算、不重新配对"的对应关系断言(契约 1 §6)。