输入格式与验证契约
本页将资料索引中的来源落实为首版接受规则。规范依据为固定镜像,下述 API 行为是首版输入契约,实际入口见源码生成参考,样本已存在不代表兼容性已通过。
在线文件/HTTP 来源也可按来源 ID 显式注入 JsonReader;自定义 reader_profile_id 参与恢复身份,输出仍统一检查完整性、能力、时效和大小。纯解析与在线来源共用同一适配器协议,入口见公共 API。
JSON 支持矩阵
| format ID | 首批兼容目标 | 映射与限制 |
|---|---|---|
| routinator-json | Routinator 0.15.2 的 JSON 输出形状 | roas、routerKeys、aspas;ASN 为 AS 加十进制数字;metadata.generated / generatedTime |
| routinator-jsonext | 同 tag 的 JSONExt 输出形状 | 同上,另保存 source 元数据及已识别的有效期约束 |
| rpki-client-json | rpki-client 9.9 输出源码描述的形状 | 整数 ASN、metadata.buildtime、bgpsec_keys、customer_asid、逐条 expires |
生产导出子集的软件版本未知,不标成“已验证 rpki-client 9.9”。其他生产者版本只在匹配上述形状并通过相关样本后扩充矩阵;格式识别成功不等于承诺该软件全部输出兼容。
auto 使用已识别的 metadata 和互斥字段特征识别;无特征或混合特征时要求显式 format。不能因为某个数组为空就猜生产者,也不使用文件扩展名决定语义。Routinator JSON 与 JSONExt 共用 metadata;当所有载荷数组均为空或缺失时,auto 无法区分二者,必须显式选择 routinator-json 或 routinator-jsonext。显式格式仍保留缺失与已同步为空的区别。本库多来源导出使用独立 load_snapshot;parse_json 识别到该格式时提示改用相应入口,避免重新赋予来源身份或有效期。
所有内置适配器检查整个文档,拒绝重复 JSON key、非法 UTF-8、非有限数值、错误字段类型和超限输入。可识别但不参与本库语义的 metadata/顶层扩展字段可以忽略并记入诊断。上表固定的现代生产者格式不定义 ASPA afi,内置适配器仍拒绝该未知语义字段,不把历史生产者布局自动套入现代格式;旧 RTR -10 的显式 AFI 支持不等于任意历史 JSON 均受支持。自定义 JsonReader 与程序化 ParsedDataset 可用 Aspa.afi/aspa_families 明确表达单族原始范围和完整覆盖,遵循数据契约,不隐式提升为双族。
字段与完整性
| 数据 | 必填字段和规则 |
|---|---|
| ROA / VRP | prefix、maxLength、asn;严格 CIDR 网络地址,maxLength 合法,ASN 不接受 bool;AS0 VRP 保留 |
| ASPA | customer 或 customer_asid、providers;customer 为正 ASN,非空 providers、没有自身、没有重复;接受合法 JSON 数组顺序后规范化排序 |
| Router Key | asn、SKI/ski、routerPublicKey/pubkey;SKI 精确为 20 字节,按生产者的 hex/base64 表示解码;保留 SPKI 字节 |
| 集合 | 缺少字段为 unsupported,显式空数组在完整接纳后为 ready_empty;null 不等于空数组 |
| 时间 | 格式声明的时间字段必须可解析;两份等价时间表示同时存在时必须一致 |
Routinator 公钥编码与 rpki-client 公钥编码分别按固定生产者的输出方式解码,不把 SLURM 的编码规则套在普通 JSON 上。Router Key 首版检查字节编码、长度与协议承载要求,不执行公钥签名验证或证书链验证;不将“字节可解析”描述成有效密钥。
ASPA 单条 providers 中 AS0 只能独占;重复 customer 的多条合法 JSON 记录先保留各自支持,再分别按有效 AFI 形成并集。合并后若存在非零 provider,生效并集移除 AS0 标志,原始支持保留;依据 aspa-profile-29 §5.2。RTR 的单来源 customer/AFI 替换规则单独执行,不能套用 JSON 多对象合并。
完全相同的 JSON VRP 可去重;保留逐条支持期限以避免把较短期限误授予较长寿命。上游 metadata.roas 往往是对象数量,不能拿来比 VRP 行数。仅对明确等于输出集合大小的字段建立生产者专用检查,例如 rpki-client uniquevrps;存在时不符则完整来源接纳失败。
解析层允许返回含完整性问题的 ParsedDataset,供离线字段研究;store.replace_source 拒绝不完整数据。现有 production-subset 样本保留完整导出 metadata,因此只能用于字段解析测试,不能借 offline 模式绕过完整性要求。
上游 CCR 哈希首版保存为未验证 metadata,不宣称已检查 CCR;本库导出自身的哈希用于文件完整性,不能代替上游密码学验证或来源认证。
来源接纳表示宿主选择该来源在声明范围内提供验证数据;库无法从任意 JSON 证明其覆盖全网。已知按 ASN/前缀过滤的样本仅用于字段研究,不能据此建立全局 ROV 视图。首版在线来源要求调用方提供其所需验证范围的完整数据,不增加部分范围数据的自动推断。
生成时间与有效期限
FreshnessPolicy 必须显式提供 max_age 或绝对 valid_until。使用 max_age 必须有可接受的原始生成时间;缺少时间时可由宿主指定绝对 valid_until。不能从下载时间、文件 mtime、HTTP Date 或每次加载的当前时间推导新的生成时间。
来源整体期限取生成时间加 max_age 与显式 valid_until 中适用项的最早值;记录期限再取其原始 expires 与来源期限的最早值。Routinator JSONExt 的已识别对象 validity、chainValidity、stale 只能收紧期限。对于 source 中每个对象都支持完整相同载荷值的 VRP/Router Key,多份支持分别计算,某一支持失效不删除另一支持。例外对象没有链时间时仍受来源整体期限约束。
JSONExt ASPA 另行处理:Routinator 0.15.2 已将同 customer 的 providers 合并,source 数组只有对象元数据,没有每个对象各自授权的 provider 集合。因此不得把 source 中每个对象都当作最终并集的完整支持。首版对该导出条目的整个 provider 集合采用来源整体期限与所有已知对象期限的最早值;到期时撤销该条目整体支持,等待新的完整导出,不能猜测仅删除哪些 provider。其他独立输入条目或其他来源的有效支持仍可保留。原始对象标签可用于诊断,但不能冒充已知的 provider→对象关联。依据:固定输出实现与同一提交的合并逻辑。
例如对象 A 授权 P1 到 T1、对象 B 授权 P2 到 T2,且 T1 < T2;导出只剩并集 {P1,P2} 与 A/B 时间。不能在 T1 后用 B 的期限继续支持 P1,也不能从导出推断 B 只支持 P2;按上述规则整个条目在 T1 失效。此保守失效属于本库对有信息损失的输入格式的接纳策略,不声称恢复了原始 ASPA 对象。
解析历史输入不意味着拒绝其字节;接纳时按 EvaluationContext 判断可用性。在线不服务已经到期的内容;离线只在显式参考时刻计算结果并保留原时间。超出配置 clock_tolerance 的未来生成时间不可用于在线授予寿命。
完整性通过但所有记录已自然到期且来源仍有效时,可用集合为空;来源整体到期则不可用。原始状态仍保留过期记录供解释和重新合并,不能再用于 RTR 增量恢复。
评价窗口统一为 valid_from <= t < expires_at。已知 generated_at 是整个数据集的评价下界;offline reference_time 早于该时刻时接纳报 InputError(code="invalid_evaluation_time"),解析层仍可检查历史字节。JSONExt 的 notBefore 和 chainValidity.notBefore 取最大下界;多个来源对象聚合的 ASPA 对所有已知下界取最大值、上界取最小值。不在窗口的原始支持保留但不生效,未来激活边界进入 usable_until。生产者、程序化数据集和导出重载共用这一规则。
Routinator 0.15.2 Router Key 使用 URL-safe、无 padding base64;rpki-client 使用标准带 padding base64。编码检查拒绝非规范尾比特和混淆的字母表,不以“某种 base64 可以解码”作为接纳依据。
文件和 HTTP 更新
文件更新先读取完整候选,检查打开前后文件身份、大小和修改迹象;发现并发修改重试,不接纳半次写入。不能仅凭相同文件名或 mtime 认为内容可靠。业务原子性以解析和完整性检查通过为准,建议生产者采用临时文件替换。
HTTP 获取只接纳成功的完整 200 JSON 响应。首版不跟随重定向,不从环境读取代理、认证或证书配置,不维护响应 cookie。HTTP 来源使用 http extra 的 HTTPX 公共传输接口;核心导入及本地文件来源不要求安装 HTTPX。request_timeout 是包含资源准入等待、下载、解析和发布的总期限,字节到达不重置期限;取消期间受管理的阻塞解析须完成清理,超时后的结果不得发布。
默认 HTTP/1.1 传输经 HTTPcore 的公开连接池及 network backend 接口管理 TCP/TLS,连接所有权与取消清理见生命周期。HTTPX 和 HTTPcore 均显式属于 http/service extra;不从第三方私有模块导入网络实现,也不修改全局连接函数。TLS 信任配置的文件读取在受管理线程中完成,关闭等待已开始的准备工作并释放迟到资源。
默认 HTTPS 与 HTTPX trust_env=False 的既有行为一致,使用 certifi CA 集合;不追加操作系统证书库,也不读取 SSL_CERT_FILE/SSL_CERT_DIR。显式 ssl_context 由宿主选择信任集合;trust_profile_id 是恢复身份,默认字符串 system-trust 不表示加载操作系统附加证书。SDK 默认传输遵守相同规则,CLI --remote-ca-file 显式选择 CA 后仍使用本库管理的连接与取消清理。
下载原始字节受 max_staging_wire_bytes 限制,解压后字节同时受 max_json_bytes 和 max_staging_wire_bytes 限制。支持无压缩、gzip(含串联成员)和带 zlib 头的 deflate;其他 Content-Encoding 明确拒绝。增量解压限制每次输出,不先分配完整解压结果再检查;压缩流截断、尾部不完整或格式错误使整个候选失败。
请求凭据、URL 路径/查询、响应 cookie 和服务端错误文本不进入来源错误或库日志。实现不修改宿主 logger:通过每请求的 HTTPcore trace 扩展 清除完成及失败事件的日志参数,保留启动事件所需的连接参数。此行为已在 HTTPX 0.28.1 / HTTPcore 1.0.9 的实际 DEBUG 日志上回归,宿主其他 HTTP 客户端不受影响;trace 文档没有承诺未来版本的日志与回调顺序,依赖升级需重新执行含认证、Set-Cookie 和恶意响应原因文本的日志测试。
ETag/Last-Modified 只有在对应 200 候选完成接纳后才保存为当前条件请求状态。304 只证明表示未变,不延长原始期限;本地没有匹配内容或身份改变时,取消条件头重新获取。ETag 不是签名或数据新鲜度证明。
重复文件读取或相同内容的 HTTP 200 仍完整解析和接纳;若发布层复用既有不可变数据集,来源 worker 仅保存已接纳的来源元数据,不额外持有未采用的候选副本。调用方持有的有效快照仍可继续使用;这不承诺关闭 Client 后 RSS 立即回到启动基线。
错误响应、超时、200 的畸形 JSON、失败完整性检查均保留仍有效的旧状态。退避不早于有效 Retry-After;达到原始期限独立使数据失效。HTTP 缓存时效与载荷时效分别处理,依据 RFC 9110 §13/§15.4.5 和 RFC 9111 §4。
ROV
依据 RFC 6811 §2 及 RFC 8481。调用方负责从 BGP 属性确定起源 ASN;本库单条接口的 asn 接受整数或 None,None 对应规范的 NONE。起源 AS0 和 None 均不能匹配任何 VRP;是否丢弃 BGP 路由由应用负责。
- 先校验输入和所需 VRP 可用性。
- 获取同地址族全部覆盖 VRP;没有覆盖为 notfound。
- 任意覆盖 VRP 同时满足非零起源 ASN 相等及路由长度不大于 max_length,为 valid。
- 有覆盖但无匹配,为 invalid。详细结果对每个覆盖项分别记录 ASN、长度不符,允许两者同时出现。
不能只取最长匹配,不能按输入 ASN 预过滤覆盖集合,也不能用“VRP 集合没加载”返回 notfound。
标准 ASPA 输入
依据 aspa-verification-28 §5。输入 path 按 BGP 展示顺序从邻居到起源;调用方按 RFC 6793 完成 AS_PATH / AS4_PATH 重建,本库不接收原始 BGP UPDATE,也不猜测 AS_TRANS 的实际 ASN。
相邻 AS_SEQUENCE 可拼接,然后仅压缩相邻重复 ASN;不全局去重。包含 AS_SET 的可解析路径按草案得 invalid;空路径、邻居 ASN 不符按对应步骤得 invalid。畸形类型、ASN 越界、AS0 路径、空的内部段则为 InputError,区别于语法合法但算法判为 invalid 的路径。
首版标准接口只处理外部 AS 路径。带 confed_sequence 或 confed_set 时返回 unsupported_path_context,调用方须按其 BGP 上下文提供重建后的外部路径;库不能悄悄删除段或把内部 ASN 当外部 customer。复杂商业关系由调用方为该路由明确提供实际 relationship,不按 ASN 推测。
| relationship,从本地接收方看邻居 | 算法 | 首 ASN 检查 |
|---|---|---|
| customer、peer | §5.5 upstream | 必须等于 neighbor_asn |
| route_server_client,本地为 RS | §5.5 upstream | 必须等于 neighbor_asn |
| route_server,本地为 RS-client | §5.5 upstream | 按草案的 RS-client 例外处理,不插入透明 RS 的 ASN |
| provider | §5.6 downstream | 必须等于 neighbor_asn |
local_asn 不自动插入路径。上下文缺少必填字段属于 InputError,不能冒充标准 unknown;unknown 专指在可用 ASPA 数据集上缺少所需授权证明。
标准 ASPA 判定
§5.3 的 provider 查询对不同 ASN x、y 返回:x 没有 ASPA 记录为 No Attestation;存在且 y 在 provider 集合中为 Provider+;存在但不包含 y 为 Not Provider+。AS0 标志使所有正常 y 不获授权,但不等同于没有记录。
以压缩路径反向编号 A(1) 为起源、A(N) 为邻居。up-ramp 从起源端沿 customer→provider 查询;down-ramp 从邻居端反方向查询。最小坡长在首个缺证明或明确否定处停止,最大坡长仅在明确否定处停止;没有停止项则取 N。长度是节点数,避免用边数造成差一错误。
upstream 在前置检查后依次判定 max_up < N 为 invalid,min_up < N 为 unknown,否则 valid。downstream 依次判定 max_up + max_down < N 为 invalid,min_up + min_down < N 为 unknown,否则 valid。完整分支和边界必须对应固定草案 §5.4–5.6,不能套用旧草案的不同算法。
BMP 保守分析
BmpContext 保存观察阶段、已知 local/neighbor ASN、可选 relationship 及调用方确认的外部路径方向;这些信息不能从一个不明方向的 ASN 列表自动推断。
首版仅在路径方向和重建责任明确时分析。上下文完整时可在解释中附标准验证结果,但顶层仍返回 BmpAnalysis。上下文不全时列出所有与已知事实相容且可检查的场景;存在无法建模的场景或缺少数据证明则 indeterminate。
只有所有可能场景都明确 invalid 才报告 invalid。所有场景均有充分证据且未见 invalid 时为 no_invalid_evidence;它不保证真实路由通过标准验证。存在 valid/invalid 分歧或 unknown 时为 indeterminate。不能通过任选一种邻居关系制造确定性。
数据本身不可用仍抛 DataUnavailableError,不转成分析的 indeterminate。标准结果与分析结果使用独立类型、独立序列化 kind 和文档入口。