08 Constraints中文
08 · 约束、遗留义务与 Resolve
规范来源:
capability-language-core-v1.md§8 本页是便于阅读的指南。若出现冲突,以规范为准。 状态:预览版——不用于生产环境。
速览
约束限制 capability 的使用方式。v1 core 恰好识别三对 (scheme, type);只有 max_rows 有 core evaluator。已识别但未求值的约束必须以 allow_unresolved + unresolved 保留在 verdict 上——绝不能静默丢弃。Resolve 按义务闭合 consumer 的反馈回路。
1. 约束身份:(scheme, type)
约束使用冒号记法三元组 scheme:type[:params];身份是二元组 (scheme, type),绝不只是 type 名称(§8.1)。
varwof/constraint-v1 : max_rows (core evaluator exists)
varwof/constraint-v1 : time (validated, not evaluated)
varwof/constraint-v1 : network (validated, not evaluated)
std/database-v1:max_rows不被识别——scheme 范围很重要(§8.1)。未识别的二元组 →deny("unknown_constraint"),按 fail-closed 处理(decide-003unknown:constraint:type;payments-002是 scheme 范围内的payments:quota:daily,不在 v1 已知集合中)。- 已识别的二元组必须符合该类型的值语法;不符合 →
deny("invalid_constraint")。
2. 值语法(§8.1)
| type | 合法值(v1) | core 行为 |
|---|---|---|
max_rows |
严格非负整数 | 针对 op params 求值 |
time:window |
JSON 数组(≤ 32),每个元素为 {"start":"HH:MM[:SS]","end":"HH:MM[:SS]"};UTC 区段;区段升序、不重叠,采用半开 [start, end),单个区段不得跨越午夜 |
仅识别 |
network:cidr |
合法 IPv4/IPv6 CIDR 字符串的 JSON 数组(≤ 32) | 仅识别 |
语法陷阱(每种情况都有 vector 固定):
- 标量 time:window:3600 不是合法的 time:window 值 → invalid_constraint(decide-021)。
- 没有前缀长度的 CIDR → invalid_constraint(decide-022)。
- 跨越午夜的单个区段(22:00→06:00)必须拆成 22:00→00:00 + 00:00→06:00(decide-019 → invalid_constraint)。end 值 "00:00" 会被读作 86400(次日午夜):22:00→00:00 合法,因为比较依据是一天中的秒数,而不是词法字符串顺序(§8.1)。
Operation 侧的 max_rows 定义域(修订 CLC-1.4):缺失、字符串、布尔值、负数、小数或非有限值 → max_rows:violated(无法证明符合 = fail-closed)。以下 vector 均固定为 max_rows:violated:decide-023(缺失)、decide-031("garbage")、decide-032(true)、decide-033(-1)、decide-034(1.5)。
Core 按二元组识别,但只求值 max_rows。 time/network 的求值由声明它们的 scheme 负责(§11);core 对其他二元组的拒绝是 fail-closed,可防止跨 scheme 污染:某个 scheme 自己定义的 max_rows 不会被 Core 的求值器劫持(§8.1)。
3. 遗留义务通道(§8.4)
已识别且值符合 §8.1 语法、但 v1 core 没有求值器的约束(time、network)MUST NOT 被丢弃:它会出现在决策的附加 unresolved 列表中,verdict 为 allow_unresolved——这是一个独立的枚举值,绝不等于 allow(decide-020 network:cidr;decide-024 拆分跨午夜窗口,二者都只是被识别)。
Fail-closed 边界: consumer(PEP / profile / 声明 scheme)在放行前必须求值或确认每个 unresolved 约束;如果无法做到,就必须 deny。只检查 if verdict == "allow" 的 consumer 不能依据字面枚举值,把遗留义务当作已经满足的 allow 放行(§8.4)。
unresolved的顺序(§8.4,修订 CLC-1.15):使用规范化字符串,折叠重复项,并按 UTF-8 字节序列排序——使用 §7.1 的 collation,而不是 ECMAScript 默认(UTF-16 码元)顺序。输出前只连接一次,并且只排序一次。- 组合义务(consumer 侧):同一
(scheme,type)的多个unresolved构成合取(AND)——满足 A 和 B 就满足全部;禁止 OR、任选其一、首个胜出或忽略其中一部分。不同(scheme,type)之间不会相互影响(§8.4)。
4. Resolve——consumer 的反馈回路(§8.5)
Resolution = { constraint: string, status: "satisfied" | "violated" | "unknown" }
Resolve(decision, resolutions, now?) → Decision
按以下顺序处理:(1) 终态 verdict 固定——deny/allow 原样返回,忽略 resolutions;(2) 输入格式错误时 fail-closed——错误的 status/约束 → invalid_resolution,错误的 now → invalid_timestamp;(3) 履行义务——对每个义务,按 violated ≻ satisfied ≻ unknown 合并 core 时钟与 consumer resolutions;(4) 重复条目也按同样方式合并;(5) 忽略无关 resolutions(O 才是权威依据);(6) 任一项被违反 → deny({type}:violated);全部满足 → allow;否则为 allow_unresolved,并保留仍为 unknown 的子集。
Core 时钟: 如果提供了 now,值类型为 §8.1 窗口数组的 varwof/constraint-v1:time 义务由 core 求值:在区段内 → satisfied,在区段外 → time:violated(resolve-015:now=21:00 在 [22:00,24:00) 之外;格式错误的 now 在 resolve-024 中被拒绝)。其他情况:部分满足 → allow_unresolved,并保留剩余项(resolve-006);任一项被违反 → deny,并给出相应的 {type}:violated(resolve-009);O 之外的 resolution 会被忽略(resolve-013);无法识别的 status → invalid_resolution(resolve-023)。
不得超出时间范围缓存: core 时钟完成的义务只在调用瞬间有效。依据 Resolve 结果采取行动的 consumer,必须在行动前立即用当前 now 重新调用,或者不得缓存到当前区段结束之后——缓存的 allow 不能比其窗口活得更久(§8.5)。
Resolve 是确定性、fail-closed、幂等(Resolve(Resolve(d,r,now),r,now) = Resolve(d,r,now))且单调的。它既不会创造义务,也不会丢弃义务。
防混用清单
- [ ] 身份是
(scheme,type):foo/database-v1:max_rows是unknown_constraint,绝不会被 Core 的求值器处理。 - [ ] 已识别但未求值 ⇒
allow_unresolved+unresolved——allow_unresolved不是allow。 - [ ] 语法拒绝是
invalid_constraint(值不符合语法),不同于unknown_constraint(二元组未被识别)。 - [ ] 跨越午夜的
time:window拆成两个同日区段;end中的"00:00"= 86400。 - [ ]
Resolve不会让deny复活,不会通过无关 resolution 扩大权限,并且会把缺少now的time义务解析为unknown(没有 TTL)。
常见误区
- 静默跳过未求值的约束——这是 conformance bug;遗留义务是附加的(§8.4)。
- 误以为
time/network已经求值——core 只识别值语法;求值属于声明它们的 scheme。 - 把
Resolve的 allow 缓存到区段结束之后——这会让缓存结果超出其履行范围(§8.5)。
← 07-parameters.md · → 09-intersection.md · 相关:10-decisions.md、11-reason-codes.md