ERDL 语言规范

声明式 AI 治理语义规范 · v2.1

一个规范、一棵规范树、一个哈希——同一条规则、同一个输入,在任何符合规范实现上产生字节级一致的结果与哈希。

核心数字

34
节点表达式树内核(含算术 / 量词 / 聚合 / 时间 / 状态算子)
13
决策类型(ALLOW / DENY / CORRECT / REQUEST_HUMAN / ESCALATE …)
30
操作符 Simple 投影面(纯条件,最高审计等级)
3
投影面 —— Simple / Expression / Decision Table,编译到同一棵语义树
2
表达格式 —— YAML / JSON,实现无关、跨平台

为什么是 ERDL

问题ERDL 如何解决
LLM 输出是概率性的确定性的 when → then 护栏,在模型之外求值——安全边界从不放在 Prompt 里
规则跨实现漂移318 条 JCS + SHA-256 向量强制字节级一致
合规需要审计轨迹每次求值都产出密码学可验证的哈希
业务人员读不懂代码三种投影面,编译到同一棵语义树

三种投影面:同一条规则,三种写法

业务人员写「决策表」、集成者写「Simple 条件」、内核用「表达式树」——三者编译到同一棵规范树、同一个哈希。

# Simple 投影面(30 操作符,最高审计等级)
when:
  logic: AND
  conditions:
    - field: "tool.name"   operator: eq   value: "issue_refund"
    - field: "tool.args.amount"  operator: gt  value: 5000
then: REQUEST_HUMAN

同一条规则,三种语言 —— 一个非工程师能看懂哪一个?

政策条文(来自法务,一句话)

「员工不得将客户数据发送给公司域名列表之外的任何收件人。」

现在,三种语言把它写成可执行的规则。


写法一:ERDL(Simple 形态)

protocol: "erdl/v2"
metadata:
  name: "customer-data-egress"
  decision: ALLOW                        # 未命中规则时放行
rules:
  - name: "SEC-001"
    description: "客户数据不得外发"
    when:
      logic: AND
      conditions:
        - field: "data.classification"
          operator: eq
          value: "customer_data"
        - field: "recipient.domain"
          operator: not_in
          value: ["internal.example.com", "partner.example.com"]
    then: DENY
    message: "客户数据不得发送给外部域名"

引擎自动生成的自然语言(gloss 投影):

当「数据分类」等于「客户数据」,且「收件人域名」不属于 [internal.example.com, partner.example.com] 时,拒绝


写法二:Rego

package egress

import rego.v1

default allow := false                                    # ← 忘写这行就 fail-open

internal_domains := {"internal.example.com", "partner.example.com"}

internal_recipient if {                                   # ← 一个「查询」,不是「判定」
    input.recipient.domain in internal_domains
}

deny if {                                                 # ← 否定一个查询
    input.data.classification == "customer_data"
    not internal_recipient
}

allow if {                                                # ← 再否定一次
    not deny
}

写法三:Cedar

forbid(
  principal,                                             # ← 授权三元组,需懂实体模型
  action == Action::"send",                              # ← 类型化 action,需 schema
  resource
)
when {
  resource.classification == "customer_data" &&
  !(resource.recipient.domain in ["internal.example.com", "partner.example.com"])
};

一个非工程师,需要「额外懂」什么才能读对?

ERDLRegoCedar
要懂「判定」还是「查询」判定(DENY查询(allow 是一个集合)判定(forbid
要懂「默认值」吗不用(decision: ALLOW 写在明处)——default allow := false 漏写就 fail-open不用(forbid 天然禁止)
要懂「双重否定」吗不用——not internal_recipient + allow if { not deny }要一点(!
要懂「实体模型/schema」吗不用(字段就是字段)不用——principal/action/resource + 类型化
三种等号陷阱:= / == / =

结论一目了然


为什么 ERDL 能「说人话」,Rego/Cedar 不能?

根源不在「语法糖」,在语义模型

所以「普通人简介一下就能懂」不是营销话术,是语义模型的选择:当规则的语义模型和政策的语义模型同构时,读规则 ≈ 读政策;不同构时,读规则 = 先学一门工程师的抽象语言。


附:本对比中 ERDL 为真实规范语法(Simple 形态 + gloss 投影),Rego/Cedar 为「熟练工程师的正确标准写法」,未做任何丑化。

快速开始(30 秒)

bash
$ npm install @openoba/erdl
import { loadErdlFile, Evaluator } from '@openoba/erdl'

const { rules, metadata } = loadErdlFile('refund.erdl.yaml')
const result = new Evaluator().evaluate(
  rules,
  { tool: { name: 'issue_refund', args: { amount: 8000 } } },
  { fallbackDecision: metadata.decision },
)
console.log(result.decision)  // 'REQUEST_HUMAN'

规范全文

完整规范: 站内全文(中文) · English (on-site) · npm 包 @openoba/erdl