拿不到状态列表时,"local policy" 不是裁决——一份新的 agent-passport 草稿撞上了拒绝词汇表
本文引证来源 · 本文所读的草稿,逐句引用:draft-le-agent-passport-00(全文) · 系列页:datatracker · 把这个词写上议程的 side meeting 公告:WIMSE 存档,2026 年 11 月 5 日 · 缝隙所映射到的词汇表,逐句引用:draft-li-rttp-iqa-addressing-02(全文) · 该词汇表的可执行形态:iqa.org/conformance/aicent-grant-ref/(四件套,逐文件 SHA-256) · 一致性枢纽:iqa.org/conformance/ · 本文所承的早前两篇:fail-closed 的三个寄存器 · 拒绝即答案 · 姊妹双柱:RTTP(rttp://,CRI 27) · IQA(iqa://,CRI 28)
上周 WIMSE 列表上落了一份这个系列等了很久却不知自己在等的草稿:《面向自主软件代理的 Agent 护照与委托回执》——Redthread Security 的 Ben Le,10 月 30 日发布。它把代理的公钥绑定到其问责控制者与构建摘要;它记录权威从主体经委托者流向代理的每一步;它让回执链条只能收窄权威;它把签发与撤销记入 append-only、公开可验证的透明日志。宽厚地读,这正是我们双柱所描述的架构从授权一侧抵达——而且它在几乎每一处都做到了我们自己的草稿会坚持的事。然后它的撤销一节写到了结尾,六个词做了全篇其他部分小心避开的那一件事。
这句话,逐字
这是 §7 运营核心的全部,逐字引自发布文本:"Passports and receipts SHOULD carry a status claim referencing a Token Status List [STATUS-LIST]. RPs SHOULD cache status lists for no longer than their time-to-live. An RP that cannot obtain a valid status list SHOULD treat the token according to local policy, and SHOULD deny for high-value operations." 按验证者必须采取的读法——在真实时刻、通话中途——前两句是工程,第三句是耸肩加一个 SHOULD。当本地策略是某人在凌晨两点为了让故障消失而写下的一行代码时,它落到什么裁决上?落到一个默认行为上。而这个系列花了一年时间记录协议拿未写明的默认怎么办:沉默被读作同意,故障用便宜的方式解决,攻击者真正需要的那条路——恰好在无人能查验的时刻出示凭证——成了永远走得通的路。
一份议程刚把这个词写上了桌面
领域注意到的速度比本文成文还快。11 月 5 日,同一位作者宣布在 IETF 127 办一场 side meeting 讨论实现经验与 -01 方向,公开议程把三十五分钟给了所谓「-01 的开放问题」——第一个就是一个短语:fail-closed revocation。然后是控制者缓存边界与再验证;然后是传输要求与中间人;然后是 attested builds 与 pinned digests。那是我们整张阅读清单,独立抵达,以议程条目的形式。这值得停一停,因为这是最健康的信号:没有人在争不可达分支该不该 fail closed——那场争论已经结束,议程把它当作已定项。开放的问题是接下来真正要紧的:拒绝叫什么名字、它的年龄怎么记录、再验证义务延伸多远。
裁决式的回答欠什么:一个名字,不是一种情绪
Fail-closed 是方向;线上协议需要值。「拒绝」不能是完整答案的原因在于:没有理由的拒绝不可审计——它是一种情绪,而情绪无法入日志、无法比较、无法拿去对照规范驳斥。寻址草稿 draft-li-rttp-iqa-addressing-02 固定了一个按固定优先序排列的五值闭集,不可达分支欠的那个值有值得整段引用的定义:authority_not_determined——"The authority for the subject could not be determined at answer time — because the organ or the authority source could not be reached, or because the only observation available predates the request and therefore establishes nothing about the present. An unreachable source is refused under this value, never read as assent." 同一份草稿的 standing-read 规则用一行说完:"If the organ cannot be reached, the read fails closed: an organ that cannot be reached is not read as silent consent."
回执是让它成为裁决的东西
答案还有后半,恰是多数 fail-closed 之争跳过的那半:拒绝时响应携带什么。只有拒绝值仍留有这个系列不断遇到的那种静默膨胀空间——实现明明是凭过期观察拒绝的,记录上却像见过什么新鲜东西。寻址草稿的 grant reference 用一个成员封死了那个洞:"observation_as_of_ms is null whenever the observation the answer relied on is absent or not fresh, even if a later, successful observation is available at answer time." 该成员陈述的是回答实际依赖之物的年龄,不是实现碰巧见过的最新鲜之物的鲜度。把这套语法套到护照草稿的缝隙上,那六个词就有了裁决的形状:不可达分支返回 authority_not_determined,它携带的 grant reference 带 null 的 observation 成员,事后读 transcript 的审计者能机械地——不信任任何人的叙事——看见这个决定是在「无」上做出来的。
我们对 -01 会问什么
本文没有一处是抱怨;草稿是好的,side meeting 议程比好更好——它是领域收拢的公告,写成了条目清单。但在一个词上收拢不等于在线上格式上收拢,所以我们要向 -01 提的问题是任何验证者都会提的,而且按本系列的姿态是提问而非开方:状态列表不可达时,响应发出哪个值——闭集里的名字,还是 transcript 审计者无法横向比较的实现私有代码?响应是否携带它所依赖观察的年龄,还是让缓存命中冒充新鲜一瞥?拒绝值集合是否封闭——因为开放集合就是未来每一种失败模式都有自己的私有词汇,而私有词汇就是审计归于沉寂的方式。这些问题的可执行形态已经在跑:aicent-grant-ref 测闭集欠哪个拒绝值、按什么优先序、observation 成员何时必须为 null——checker 25/25,突变体 21/21——家族住在咱们的一致性枢纽上,四件套带逐文件摘要可下载,已并入 Agent-Authority-Conformance 实验室主线,随时等着被指任何回答 -01 问题的实现。
一行收束:local policy 不是裁决——状态列表不可达时,验证者欠调用者一个闭集里的具名值和一条诚实的年龄记录,因为不可验证不等于证实到反证为止;它等于不予计入,而领域自己的议程刚刚先说了这句话。