1
0
Files
DiAL/openspec/specs/probe-config/spec.md
lanyuanxiaoyao 31fd3a2a43 refactor: 统一 target name/description 可空语义,前端展示 fallback 到 id
- schema: name/description 允许省略或显式 null,TypeBox Union([Null, String])
- 类型: RawTargetConfig/ResolvedTargetBase/子类型/StoredTarget/TargetStatus name 改为 string | null
- checker resolve: name: t.name ?? null,不再 fallback 到 id
- 语义校验: 拒绝空字符串和纯空白 name
- SQLite: targets.name 列改为可空 TEXT
- 前端: 新增 getTargetDisplayName(target) 展示 name ?? id
- 测试: 覆盖 name/description null 全场景,查找改为按 id
- 文档: 更新 README/DEVELOPMENT 和 6 个 openspec specs
2026-05-17 20:12:39 +08:00

22 KiB
Raw Blame History

Purpose

定义拨测工具的 YAML 配置文件格式、解析校验规则和 CLI 启动流程。

Requirements

Requirement: YAML 配置文件格式

系统 SHALL 支持通过 YAML 配置文件定义全部运行参数,包括 server 配置、runtime 配置、可选的 variables 段、checker 默认值和 typed target 列表(含可选 group 字段。target MUST 使用 id 字段作为唯一标识符MUST 使用 type 字段声明 checker 类型SHALL 支持可选的 name 字段作为展示名称元信息SHALL 支持可选的 description 字段作为目标说明。namedescription 均 SHALL 允许省略或显式配置为 null;省略或显式 null 时解析结果 SHALL 保留为 null。HTTP 领域字段 MUST 放在 http 分组cmd 领域字段 MUST 放在 cmd 分组db 领域字段 MUST 放在 db 分组。HTTP target 的 http 分组 SHALL 支持可选的 ignoreSSL(布尔值)和 maxRedirects非负整数字段。Db target 的 db 分组 SHALL 支持 url(必填)和 query(可选)字段。

defaults.http 分组 SHALL 仅支持 headers(可选)和 maxBodyBytes(可选)字段。defaults.http 分组 MUST NOT 支持 method 字段。

Scenario: 完整配置文件解析

  • WHEN 系统启动并读取包含 server、runtime、variables、defaults、targets含 id、group 字段)的 YAML 配置文件
  • THEN 系统 SHALL 正确解析所有字段并用于初始化服务、调度引擎和对应 checker runner

Scenario: 最简 HTTP 配置文件解析

  • WHEN 系统读取只包含一个 type: http targetidhttp.url)的 YAML 配置文件(省略 server、runtime、variables、defaults 和 expect
  • THEN 系统 SHALL 使用内置默认值填充未指定的字段host=127.0.0.1, port=3000, dir=./data, interval=30s, timeout=10s, runtime.maxConcurrentChecks=20, http.method=GET, http.maxBodyBytes=100MB, http.ignoreSSL=false, http.maxRedirects=0, group="default"),并保留 name=null、description=null

Scenario: 最简 cmd 配置文件解析

  • WHEN 系统读取只包含一个 type: cmd targetidcmd.exec)的 YAML 配置文件
  • THEN 系统 SHALL 使用内置默认值填充未指定的字段interval=30s, timeout=10s, cmd.cwd 为配置文件所在目录, cmd.maxOutputBytes=100MB并保留 name=null、description=null

Scenario: per-target 配置覆盖全局默认值

  • WHEN 某个 target 指定 interval、timeout 或对应领域分组中的默认字段
  • THEN 该 target SHALL 使用其自身的值,不受 defaults 中对应字段影响

Scenario: HTTP target 配置 ignoreSSL

  • WHEN YAML 配置中 HTTP target 设置 http.ignoreSSL: true
  • THEN 系统 SHALL 解析该字段并在执行时跳过 SSL 证书校验

Scenario: HTTP target 配置 maxRedirects

  • WHEN YAML 配置中 HTTP target 设置 http.maxRedirects: 5
  • THEN 系统 SHALL 解析该字段并在执行时允许最多跟随 5 次重定向

Scenario: 最简 db 配置文件解析

  • WHEN 系统读取只包含一个 type: db targetiddb.url)的 YAML 配置文件
  • THEN 系统 SHALL 使用内置默认值填充未指定的字段interval=30s, timeout=10s, group="default"),并保留 name=null、description=null

Scenario: defaults.http.method 触发校验错误

  • WHEN 配置文件中出现 defaults.http.method 字段
  • THEN 系统 SHALL 以配置错误退出,提示 defaults.http 中存在未知字段 method

Scenario: per-target http.method 仍然有效

  • WHEN HTTP target 配置 http.method: POST
  • THEN 系统 SHALL 使用 POST 作为该 target 的请求方法

Scenario: 未配置 http.method 使用内置默认值

  • WHEN HTTP target 未配置 http.method 且 defaults.http 中无 method 字段
  • THEN 系统 SHALL 使用内置默认值 GET 作为该 target 的请求方法

Requirement: CLI 参数

系统 SHALL 通过单一命令行参数接受 YAML 配置文件路径。

Scenario: 指定配置文件启动

  • WHEN 用户执行 ./dial-server ./probes.yaml
  • THEN 系统 SHALL 读取并解析指定路径的 YAML 文件作为配置

Scenario: 未提供配置文件路径

  • WHEN 用户启动程序时未提供任何命令行参数
  • THEN 系统 SHALL 以错误退出并提示需要指定配置文件路径

Scenario: 配置文件不存在

  • WHEN 用户指定的配置文件路径不存在
  • THEN 系统 SHALL 以错误退出并提示文件不存在

Requirement: 配置校验

系统 SHALL 在启动时对 YAML 配置进行完整校验,校验失败时以非零状态退出并输出清晰的错误信息。系统 SHALL 使用 TypeBox 定义配置契约和 raw config TypeScript 类型,由 Ajv 校验 TypeBox 生成的 JSON Schema再执行启动期语义 validator。配置加载流程 SHALL 明确区分 RawProbeConfigValidatedProbeConfigResolvedConfig 三段生命周期,并在 YAML 解析之后、AJV 校验之前执行变量替换阶段。JSON Schema 契约 SHALL 覆盖业务无关的结构规则,包括字段类型、必填字段、枚举、数组与对象形状、数值范围和未知字段。语义 validator SHALL 覆盖契约不适合表达的业务规则,包括 target id 唯一性、id 命名规则校验、checker type 注册状态、时长和大小解析、HTTP URL、正则可编译、JSONPath 子集和 XPath 可编译。

契约校验和语义 validator SHALL 统一产出 ConfigValidationIssue,最终由配置加载流程统一渲染为中文错误信息。

系统 SHALL 导出完整 probe-config.schema.json,该文件 SHALL 与运行期 TypeBox fragments 生成的 JSON Schema 保持一致,用于用户配置引用和编辑器提示。

headersenvvariables 等明确声明为动态键值表的对象外,配置中的未知字段 SHALL 导致启动期配置错误。系统 MUST NOT 静默忽略未知字段。

Scenario: target 缺少必填字段

  • WHEN YAML 中某个 target 缺少 id 或 type 字段
  • THEN 系统 SHALL 以错误退出,提示哪个 target 缺少哪个字段

Scenario: HTTP target 缺少 url

  • WHEN YAML 中某个 target 配置 type: http 但缺少 http.url
  • THEN 系统 SHALL 以错误退出,提示该 target 缺少 http.url 字段

Scenario: cmd target 缺少 exec

  • WHEN YAML 中某个 target 配置 type: cmd 但缺少 cmd.exec
  • THEN 系统 SHALL 以错误退出,提示该 target 缺少 cmd.exec 字段

Scenario: target type 非法

  • WHEN YAML 中某个 target 的 type 不是已注册 checker 类型
  • THEN 系统 SHALL 以错误退出,提示不支持的 target type 和当前支持的 type 列表

Scenario: target id 重复

  • WHEN YAML 中存在两个 id 相同的 target
  • THEN 系统 SHALL 以错误退出,提示重复的 id

Scenario: target id 不合法

  • WHEN YAML 中某个 target 的 id 不符合 [a-zA-Z0-9][a-zA-Z0-9_-]* 规则
  • THEN 系统 SHALL 以错误退出,提示 id 命名不合法

Scenario: group 字段类型校验

  • WHEN YAML 中某个 target 的 group 字段不是字符串
  • THEN 系统 SHALL 以错误退出并提示 group 字段类型错误

Scenario: interval 格式非法

  • WHEN interval 或 timeout 值不是有效的时长格式(如 30s5m500ms
  • THEN 系统 SHALL 以错误退出并提示格式错误

Scenario: maxConcurrentChecks 非法

  • WHEN runtime.maxConcurrentChecks 不是正整数
  • THEN 系统 SHALL 以错误退出并提示 runtime.maxConcurrentChecks 格式错误

Scenario: interval 或 timeout 解析结果非法

  • WHEN interval 或 timeout 解析结果不是正整数毫秒(如 0ms1.5ms
  • THEN 系统 SHALL 以错误退出并提示必须为正整数毫秒

Scenario: size 格式非法

  • WHEN maxBodyBytes 或 maxOutputBytes 值不是有效的 size 格式
  • THEN 系统 SHALL 以错误退出并提示支持 B、KB、MB、GB 格式

Scenario: size 解析结果非法

  • WHEN maxBodyBytes 或 maxOutputBytes 解析结果不是非负安全整数字节数(如 1.5B
  • THEN 系统 SHALL 以错误退出并提示必须为非负安全整数字节数

Scenario: HTTP method 非法

  • WHEN YAML 中某个 HTTP target 的 http.method 不是 GET、HEAD、POST、PUT、PATCH、DELETE、OPTIONS 之一
  • THEN 系统 SHALL 以错误退出,提示该 target 的 method 不合法

Scenario: HTTP method 小写非法

  • WHEN YAML 中某个 HTTP target 配置 http.method: get
  • THEN 系统 SHALL 以错误退出,提示该 target 的 method 必须为大写枚举值

Scenario: URL 格式非法

  • WHEN YAML 中某个 HTTP target 的 http.url 不是合法 URL或协议不是 http: / https:
  • THEN 系统 SHALL 以错误退出,提示该 target 的 URL 格式不合法

Scenario: maxRedirects 非法

  • WHEN YAML 中某个 HTTP target 的 http.maxRedirects 为负数
  • THEN 系统 SHALL 以错误退出,提示该 target 的 maxRedirects 必须为非负整数

Scenario: maxRedirects 非整数非法

  • WHEN YAML 中某个 HTTP target 的 http.maxRedirects 不是非负整数(如 1.5"5"
  • THEN 系统 SHALL 以错误退出,提示该 target 的 maxRedirects 必须为非负整数

Scenario: ignoreSSL 类型非法

  • WHEN YAML 中某个 HTTP target 的 http.ignoreSSL 不是布尔值
  • THEN 系统 SHALL 以错误退出,提示该 target 的 ignoreSSL 必须为布尔值

Scenario: HTTP headers 类型非法

  • WHEN YAML 中某个 HTTP target 的 http.headers 不是对象,或任一 header 值不是字符串
  • THEN 系统 SHALL 以错误退出,提示该 target 的 http.headers 格式错误

Scenario: HTTP body 类型非法

  • WHEN YAML 中某个 HTTP target 的 http.body 已配置但不是字符串
  • THEN 系统 SHALL 以错误退出,提示该 target 的 http.body 必须为字符串

Scenario: maxBodyBytes 数字非法

  • WHEN YAML 中某个 HTTP target 的 http.maxBodyBytes 或 defaults.http.maxBodyBytes 是负数、非整数或非安全整数
  • THEN 系统 SHALL 以错误退出,提示 maxBodyBytes 必须为非负安全整数字节数或合法 size 字符串

Scenario: status 模式非法

  • WHEN YAML 中某个 HTTP target 的 expect.status 包含不符合 1xx5xx 格式的字符串(如 "abc""2x""6xx"
  • THEN 系统 SHALL 以错误退出,提示该 target 的 status 模式不合法

Scenario: status 数字非法

  • WHEN YAML 中某个 HTTP target 的 expect.status 包含非整数或不在 100-599 范围内的数字
  • THEN 系统 SHALL 以错误退出,提示该 target 的 status 数字不合法

Scenario: maxDurationMs 非法

  • WHEN YAML 中某个 target 的 expect.maxDurationMs 不是非负有限数字
  • THEN 系统 SHALL 以错误退出,提示该 target 的 expect.maxDurationMs 格式错误

Scenario: HTTP expect headers 非法

  • WHEN YAML 中某个 HTTP target 的 expect.headers 不是对象,或某个 header 期望既不是字符串也不是合法 operator
  • THEN 系统 SHALL 以错误退出,提示该 target 的 expect.headers 格式错误

Scenario: HTTP expect body 必须为数组

  • WHEN YAML 中某个 HTTP target 的 expect.body 已配置但不是数组
  • THEN 系统 SHALL 以错误退出,提示该 target 的 expect.body 必须为数组

Scenario: HTTP body rule 缺少支持字段

  • WHEN YAML 中某个 HTTP target 的 expect.body 数组项未包含 contains、regex、json、css、xpath 任一支持字段
  • THEN 系统 SHALL 以错误退出,提示该 body rule 缺少支持的规则类型

Scenario: HTTP body rule 同时配置多个支持字段

  • WHEN YAML 中某个 HTTP target 的同一条 body rule 同时包含 contains、regex、json、css、xpath 中的多个支持字段
  • THEN 系统 SHALL 以错误退出,提示每条 body rule 只能配置一种规则类型

Scenario: HTTP body regex 非法

  • WHEN YAML 中某个 HTTP target 的 body regex 规则不是字符串或不是可编译正则表达式
  • THEN 系统 SHALL 以错误退出,提示该 body regex 不合法

Scenario: HTTP body json path 非法

  • WHEN YAML 中某个 HTTP target 的 body json 规则缺少 path或 path 不符合系统支持的 JSONPath 子集
  • THEN 系统 SHALL 以错误退出,提示该 body json path 不合法

Scenario: HTTP body css selector 非法

  • WHEN YAML 中某个 HTTP target 的 body css 规则缺少 selector或 selector 不是非空字符串
  • THEN 系统 SHALL 以错误退出,提示该 body css selector 不合法

Scenario: HTTP body xpath path 非法

  • WHEN YAML 中某个 HTTP target 的 body xpath 规则缺少 path或 path 不是非空字符串,或可被现有 XPath 库静态判定为语法错误
  • THEN 系统 SHALL 以错误退出,提示该 body xpath path 不合法

Scenario: expect operator 类型非法

  • WHEN YAML 中某个 HTTP expect operator 的 match 不是可编译正则字符串empty/exists 不是布尔值,或 gt/gte/lt/lte 不是有限数字
  • THEN 系统 SHALL 以错误退出,提示对应 operator 配置不合法

Scenario: expect operator 类型非法

  • WHEN YAML 中某个 expect operator 的 match 不是可编译正则字符串empty/exists 不是布尔值,或 gt/gte/lt/lte 不是有限数字
  • THEN 系统 SHALL 以错误退出,提示对应 operator 配置不合法

Scenario: unknown 字段失败

  • WHEN YAML 中任一结构化配置对象包含契约未声明的字段,且该对象不是明确允许动态键的对象
  • THEN 系统 SHALL 以错误退出,提示未知字段所在路径

Scenario: 动态 headers 字段允许

  • WHEN YAML 中 http.headersdefaults.http.headersexpect.headers 包含任意 header 名称,且对应值符合契约
  • THEN 系统 SHALL 接受这些动态 header 名称

Scenario: 动态 env 字段允许

  • WHEN YAML 中 cmd.env 包含任意环境变量名称,且对应值为字符串
  • THEN 系统 SHALL 接受这些动态 env 名称

Scenario: JSON Schema 不修改输入

  • WHEN 系统执行 JSON Schema 契约校验
  • THEN 系统 MUST NOT 通过契约校验器强制转换类型、注入默认值或删除未知字段

Scenario: 配置生命周期分离

  • WHEN 系统加载配置文件
  • THEN 系统 SHALL 按 unknown -> 变量替换 -> RawProbeConfig -> ValidatedProbeConfig -> ResolvedConfig 的顺序执行变量替换、契约校验、语义校验和运行期配置解析

Scenario: 结构化校验 issue

  • WHEN 契约校验、语义 validator 或变量替换阶段发现非法配置
  • THEN 系统 SHALL 先生成包含 code、path、message 和可选 targetName 的结构化 ConfigValidationIssue,再统一渲染为中文错误信息

Scenario: 导出配置 JSON Schema

  • WHEN 仓库生成或检查配置契约
  • THEN 根目录 SHALL 存在 draft-07 probe-config.schema.json,且其内容 SHALL 与当前公共 fragments 和已注册 checker fragments 组装出的完整 schema 一致(包含 variables 段和 target 的 id/name 字段) 系统 SHALL 支持使用单位字符串配置读取上限,单位包括 BKBMBGB

Scenario: 解析 MB

  • WHEN YAML 中配置 maxBodyBytes: "100MB"
  • THEN 系统 SHALL 将其解析为 104857600 bytes

Scenario: 解析 KB

  • WHEN YAML 中配置 maxOutputBytes: "512KB"
  • THEN 系统 SHALL 将其解析为 524288 bytes

Requirement: runtime 并发配置

系统 SHALL 支持 runtime.maxConcurrentChecks 配置全局最大并发检查数。

Scenario: 使用默认并发限制

  • WHEN YAML 中未配置 runtime.maxConcurrentChecks
  • THEN 系统 SHALL 使用默认值 20

Scenario: 配置并发限制

  • WHEN YAML 中配置 runtime.maxConcurrentChecks: 5
  • THEN 系统 SHALL 将全局最大并发检查数设置为 5

Requirement: YAML 配置使用 Bun 内置解析

系统 SHALL 使用 Bun 内置的 Bun.YAML.parse() 解析配置文件,不引入外部 YAML 解析库。

Scenario: 解析 YAML 内容

  • WHEN 系统读取 YAML 文件内容
  • THEN 系统 SHALL 调用 Bun.YAML.parse() 将内容解析为配置对象

Requirement: expect 配置增强

系统 SHALL 支持 typed target 的领域专用 expect 配置,包括 HTTP 的 status(支持精确数字和范围模式)、headersbody 和 cmd 的 exitCodestdoutstderr。内容类 expect MUST 使用数组表达配置顺序。

Scenario: 解析 HTTP expect 配置

  • WHEN YAML 配置文件中 HTTP target 的 expect 包含 status、headers、body 规则数组及内部方法
  • THEN 系统 SHALL 正确解析并存储为 HTTP target 的 expect 字段

Scenario: 解析 cmd expect 配置

  • WHEN YAML 配置文件中 cmd target 的 expect 包含 exitCode、stdout 和 stderr 规则数组
  • THEN 系统 SHALL 正确解析并存储为 cmd target 的 expect 字段

Scenario: 解析 body 有序规则数组

  • WHEN YAML 中 HTTP target 配置 expect.body 为 contains、json、regex 三个数组项
  • THEN 系统 SHALL 保留数组顺序,供执行阶段按配置顺序快速失败

Scenario: 不配置 HTTP status

  • WHEN HTTP target 未配置 expect.status
  • THEN 系统 SHALL 在执行 expect 时使用默认 status: [200] 语义

Scenario: 配置 HTTP status 范围模式

  • WHEN HTTP target 配置 expect.status: ["2xx"]
  • THEN 系统 SHALL 在执行 expect 时匹配所有 200-299 状态码

Scenario: 配置 HTTP status 混合模式

  • WHEN HTTP target 配置 expect.status: ["2xx", 301]
  • THEN 系统 SHALL 在执行 expect 时匹配所有 200-299 状态码或精确匹配 301

Scenario: 不配置 cmd exitCode

  • WHEN cmd target 未配置 expect.exitCode
  • THEN 系统 SHALL 在执行 expect 时使用默认 exitCode: [0] 语义

Scenario: 不配置 expect

  • WHEN target 未配置任何 expect 规则
  • THEN 系统 SHALL 正常处理expect 字段为 undefined

Requirement: 数据保留配置字段

配置 schema 的 runtime 段 SHALL 支持 retention 字段,类型为字符串,格式为 <数字><单位>(单位:d 天、h 小时、m 分钟),用于指定历史数据保留时长。

Scenario: retention 字段校验通过

  • WHEN 配置文件中 runtime.retention 为合法格式(如 "7d""24h""30m"
  • THEN 配置校验 SHALL 通过

Scenario: retention 字段格式非法

  • WHEN 配置文件中 runtime.retention 为非法格式(如 "abc""7x"""
  • THEN 配置校验 SHALL 失败并报告格式错误

Scenario: retention 字段缺省

  • WHEN 配置文件中未指定 runtime.retention
  • THEN 系统 SHALL 使用默认值 "7d"

Requirement: 数据目录路径解析

配置加载流程 SHALL 将 server.dataDir 相对路径基于配置文件所在目录configDir解析为绝对路径。绝对路径 SHALL 保持不变。

Scenario: dataDir 为相对路径

  • WHEN 配置文件位于 /opt/dial/probes.yaml,且 server.dataDir 配置为 ./data
  • THEN 系统 SHALL 将 dataDir 解析为 /opt/dial/data,而非依赖进程 cwd

Scenario: dataDir 为绝对路径

  • WHEN server.dataDir 配置为 /var/lib/dial/data
  • THEN 系统 SHALL 直接使用该绝对路径,不做额外解析

Scenario: dataDir 使用默认值

  • WHEN 未配置 server.dataDir(使用默认值 ./data
  • THEN 系统 SHALL 将默认值 ./data 基于 configDir 解析为绝对路径

Requirement: target 通用元信息字段约束

系统 SHALL 在 YAML target 通用字段中支持 description 字段,并对 idnamedescription 执行契约校验。id MUST 为 1 到 30 个字符。name MUST 为 null 或 1 到 30 个字符的字符串,且语义校验 SHALL 拒绝仅包含空白字符的 name。description MUST 为 null 或不超过 500 个字符的字符串,且 MAY 为空字符串。

Scenario: description 字段解析

  • WHEN 系统读取包含 description: "检查生产 API 健康状态" 的 target
  • THEN 系统 SHALL 将该字段解析为 target 的目标说明

Scenario: name 为 null 通过校验

  • WHEN 系统读取包含 name: null 或省略 name 的 target
  • THEN 系统 SHALL 接受该配置

Scenario: name 仅包含空白字符报错

  • WHEN 系统读取包含 name: " " 的 target
  • THEN 系统 SHALL 以配置错误退出,提示 name 不能为空白

Scenario: description 为空字符串

  • WHEN 系统读取包含 description: "" 的 target
  • THEN 系统 SHALL 接受该配置,且不触发长度错误

Scenario: description 为 null 通过校验

  • WHEN 系统读取包含 description: null 或省略 description 的 target
  • THEN 系统 SHALL 接受该配置

Scenario: description 类型非法

  • WHEN YAML 中某个 target 的 description 字段不是字符串也不是 null
  • THEN 系统 SHALL 以错误退出,提示 description 字段类型错误

Scenario: description 超过最大长度

  • WHEN YAML 中某个 target 的 description 字段超过 500 个字符
  • THEN 系统 SHALL 以错误退出,提示 description 字段长度错误

Scenario: id 超过最大长度

  • WHEN YAML 中某个 target 的 id 字段超过 30 个字符
  • THEN 系统 SHALL 以错误退出,提示 id 字段长度错误

Scenario: name 超过最大长度

  • WHEN YAML 中某个 target 的 name 字段超过 30 个字符
  • THEN 系统 SHALL 以错误退出,提示 name 字段长度错误

Scenario: 变量替换后 description 超长

  • WHEN target 的 description 通过变量替换后超过 500 个字符
  • THEN 系统 SHALL 在契约校验阶段以错误退出,提示 description 字段长度错误

Requirement: 配置 schema 导出包含 target 元信息约束

系统 SHALL 在导出的 probe-config.schema.json 中包含 target idnamedescription 的长度约束和可空类型,用于编辑器提示和外部校验。

Scenario: schema 导出 description

  • WHEN 系统导出 probe-config.schema.json
  • THEN target schema SHALL 包含可选的 description 字段,类型为 string 或 null字符串最大长度为 500

Scenario: schema 导出 id 和 name

  • WHEN 系统导出 probe-config.schema.json
  • THEN target schema SHALL 声明 id 的 minLength 为 1、maxLength 为 30并声明 name 为可选字段,类型为 string 或 null字符串的 minLength 为 1、maxLength 为 30