1
0
Files
DiAL/openspec/specs/db-checker/spec.md
lanyuanxiaoyao 60a54b483f refactor: expect 类型模型重构,Raw/Resolved 双层分离与断言基础设施内聚
- 重命名 ContentRules→ContentExpectations, KeyValueExpect→KeyedExpectations
- 新增 Raw/Resolved 双层模型:resolve 阶段物化为执行计划,store 持久化 Raw 快照
- HTTP body 按需读取:status/headers 失败或无 body expectation 时不读取 body
- 新增 displayValueExpectation() 解包 failure.expected 用户可读展示
- 修复 checkEarlyTimeout 独立 lte/lt 检查,修复 KeyedExpectations JSON Schema
- 新增 expect/value.ts(resolve/check/display)、keyed.ts、content.ts、headers.ts、status.ts
- 删除旧 normalize.ts/matcher.ts/validate-matcher.ts/key-value.ts
- 更新 DEVELOPMENT.md:expect 五层管线表、displayValueExpectation、1.7↔1.10 交叉引用
- 同步 13 个 main specs,归档 refactor-expect-type-model 变更(62/62 tasks)
2026-05-20 16:12:48 +08:00

9.7 KiB
Raw Blame History

Purpose

定义 db 类型拨测目标的配置格式、执行逻辑、expect 断言规则和启动期校验。

Requirements

Requirement: db target 配置

系统 SHALL 支持 type: db 的 target 配置,通过 db.url 描述数据库连接字符串(遵循 Bun SQL 支持的格式),通过可选的 db.query 描述待执行的 SQL 语句。

Scenario: 解析仅连接的 db target

  • WHEN YAML 中 target 配置 type: dbdb.url: "postgres://user:pass@localhost:5432/mydb",未配置 db.query
  • THEN 系统 SHALL 将其解析为 db checker仅执行连通性检测

Scenario: 解析带查询的 db target

  • WHEN YAML 中 target 配置 type: dbdb.url: "mysql://user:pass@host:3306/app"db.query: "SELECT count(*) as cnt FROM users"
  • THEN 系统 SHALL 将其解析为 db checker执行连通性检测后执行指定 SQL 并进入 expect 校验

Scenario: db target 缺少 url

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

Scenario: db.url 为空字符串

  • WHEN YAML 中 target 配置 db.url: ""
  • THEN 系统 SHALL 以配置错误退出,并提示 db.url 不能为空

Scenario: db.query 为空字符串

  • WHEN YAML 中 target 配置 db.query: ""
  • THEN 系统 SHALL 以配置错误退出,并提示 db.query 不能为空字符串(如不需要查询则不配置该字段)

Scenario: db 分组未知字段失败

  • WHEN YAML 中 db target 的 db 分组包含 timeout: 5 等未知字段
  • THEN 系统 SHALL 以配置错误退出,提示 db 分组包含未知字段

Scenario: SQLite 连接字符串

  • WHEN YAML 中 target 配置 db.url: "sqlite:///data/app.db"
  • THEN 系统 SHALL 将其解析为 db checker使用 SQLite 文件数据库

Scenario: url 格式由 Bun 运行时校验

  • WHEN YAML 中 target 配置 db.url 为 Bun 不支持的格式
  • THEN 系统 SHALL 在执行阶段捕获连接错误并作为 phase="connect" 的 failure 返回,而非在启动期校验 URL 格式

Requirement: db checker 执行

系统 SHALL 按 db target 配置连接数据库并执行查询,每次执行都新建连接并在完成后关闭。连接能力本身作为监控指标。

Scenario: 仅连接测试成功

  • WHEN db target 未配置 db.query 且数据库连接成功
  • THEN 系统 SHALL 内部执行 SELECT 1 验证连通性,记录 matched=truedurationMs

Scenario: 连接失败

  • WHEN db target 的数据库连接失败(网络不通、认证错误、数据库不存在等)
  • THEN 系统 SHALL 记录 matched=falsefailure 的 phase 为 "connect"message 包含可读错误信息

Scenario: 查询执行成功

  • WHEN db target 配置了 db.query 且 SQL 执行成功返回结果集
  • THEN 系统 SHALL 记录 durationMs(从连接开始到查询完成),并进入 expect 校验

Scenario: 查询执行失败

  • WHEN db target 配置了 db.query 且 SQL 执行报错(语法错误、权限不足、表不存在等)
  • THEN 系统 SHALL 记录 matched=falsefailure 的 phase 为 "query"message 包含数据库返回的错误信息

Scenario: 执行超时

  • WHEN db target 在 timeout 时间内未完成(连接或查询)
  • THEN 系统 SHALL 关闭连接,记录 matched=falsefailure 的 phase 为 "connect""query"取决于超时发生的阶段message 包含超时信息

Scenario: 每次执行新建连接

  • WHEN db target 被引擎调度执行
  • THEN 系统 SHALL 创建新的 SQL 连接实例max: 1执行完成后立即关闭连接close timeout: 0

Scenario: 使用 unsafe 执行用户 SQL

  • WHEN db target 配置了 db.query
  • THEN 系统 SHALL 使用 sql.unsafe(query) 执行用户配置的 SQL 文本,不限制 SQL 类型

Scenario: 响应 abort signal

  • WHEN 引擎注入的 ctx.signal 被 abort
  • THEN 系统 SHALL 立即关闭数据库连接

Requirement: db expect 校验

系统 SHALL 支持 db 专用 expect包括 durationMsrowCountrowsresult,按 durationMs、rowCount、rows、result 的阶段顺序快速失败。durationMsrowCount SHALL 使用共享 RawValueExpectation 输入,并在 resolve 阶段转换为运行期 ValueExpectationrows SHALL 保留按行索引匹配列值的语义Raw 类型为 Array<RawKeyedExpectations>外层数组按行索引内层每个元素表达该行的列值断言Resolved 类型为 Array<KeyedExpectations>。每个行规则中列值 primitive 字面量等价于 {equals: <literal>}result MUST 使用共享 RawContentExpectations 数组输入,并在运行期以 ContentExpectations 对查询结果对象 { rows, rowCount } 执行断言。

Scenario: durationMs 校验

  • WHEN db target 配置 expect.durationMs: {lte: 3000} 且实际执行耗时 4000ms
  • THEN 系统 SHALL 返回 matched=falsefailure 的 phase 为 duration

Scenario: rowCount 校验通过

  • WHEN db target 配置 expect.rowCount: { gte: 1 } 且查询返回 5 行
  • THEN 系统 SHALL 判定 rowCount 阶段通过,继续后续 expect 阶段

Scenario: rowCount 校验失败

  • WHEN db target 配置 expect.rowCount: { gte: 1 } 且查询返回 0 行
  • THEN 系统 SHALL 返回 matched=falsefailure 的 phase 为 rowCountpath 为 rowCountexpected 为 { gte: 1 }actual 为 0

Scenario: rows 按索引匹配列值 matcher 形式

  • WHEN db target 配置 expect.rows: [{ cnt: { gte: 100 } }] 且查询首行 cnt 列值为 50
  • THEN 系统 SHALL 返回 matched=falsefailure 的 phase 为 rowpath 为 rows[0].cnt

Scenario: rows 按索引匹配列值字面量形式

  • WHEN db target 配置 expect.rows: [{ status: "active" }] 且查询首行 status 列值为 "active"
  • THEN 系统 SHALL 在 resolve 阶段将该列值解析为 {equals: "active"} 并判定该行该列通过

Scenario: rows 只检查声明的列

  • WHEN db target 配置 expect.rows: [{ cnt: { gte: 1 } }] 且查询首行包含 cnt、name、age 三列
  • THEN 系统 SHALL 仅检查 cnt 列,忽略 name 和 age 列

Scenario: rows 结果行数不足

  • WHEN db target 配置 expect.rows 包含 3 个元素但查询仅返回 2 行
  • THEN 系统 SHALL 返回 matched=falsefailure 的 phase 为 rowmessage 说明结果行数不足

Scenario: result JSONPath 校验

  • WHEN db target 查询返回首行 {status: "active"} 且配置 expect.result: [{json: {path: "$.rows[0].status", equals: "active"}}]
  • THEN 系统 SHALL 基于 {rows, rowCount} 结果对象执行 JSONPath并判定 result 阶段通过

Scenario: result rowCount 校验

  • WHEN db target 查询返回 2 行且配置 expect.result: [{json: {path: "$.rowCount", equals: 2}}]
  • THEN 系统 SHALL 判定 result 阶段通过

Scenario: 无 query 时结果类 expect 被忽略

  • WHEN db target 未配置 db.query 但配置了 expect.rowCountexpect.rowsexpect.result
  • THEN 系统 SHALL 忽略这些查询结果断言(仅 durationMs 生效)

Scenario: 快速失败顺序

  • WHEN db target 同时配置 durationMs、rowCount、rows 和 result
  • THEN 系统 SHALL 按 durationMs → rowCount → rows → result 顺序校验,任一阶段失败立即返回

Requirement: db checker 启动期配置校验

系统 SHALL 在启动期对 db checker 的配置契约和语义执行严格校验。Db target 的 db 分组 SHALL 只允许 urlquery 字段。Db expect SHALL 只允许 durationMsrowCountrowsresult 字段。未知字段、非法 ValueExpectation、非法 ContentExpectations、非法 regex 和 ReDoS 风险正则 MUST 导致启动期配置错误。语义校验 MUST NOT 修改 Raw db expect 输入。

Scenario: db expect durationMs 非法

  • WHEN YAML 中 db target 配置 expect.durationMs 不是合法 RawValueExpectation
  • THEN 系统 SHALL 以配置错误退出,提示 expect.durationMs 格式错误

Scenario: db expect rowCount 非法

  • WHEN YAML 中 db target 配置 expect.rowCount 不是合法 RawValueExpectation
  • THEN 系统 SHALL 以配置错误退出,提示 expect.rowCount 格式错误

Scenario: db expect rows 非法

  • WHEN YAML 中 db target 配置 expect.rows 不是对象数组
  • THEN 系统 SHALL 以配置错误退出,提示 expect.rows 必须为对象数组

Scenario: db expect rows 元素列值非法

  • WHEN YAML 中 db target 配置 expect.rows: [{ cnt: { foo: 1 } }],其中 foo 不是合法 matcher
  • THEN 系统 SHALL 以配置错误退出,提示 rows 中包含未知 matcher

Scenario: db expect rows 对象值必须显式 equals

  • WHEN YAML 中 db target 配置 expect.rows: [{ payload: { status: "ok" } }] 且 payload 值不是合法 matcher 对象
  • THEN 系统 SHALL 以配置错误退出,提示对象值必须显式写成 {equals: {status: "ok"}}

Scenario: db expect result 非法

  • WHEN YAML 中 db target 配置 expect.result 不是合法 ContentExpectations 数组
  • THEN 系统 SHALL 以配置错误退出,提示 expect.result 格式错误

Scenario: db expect 未知字段失败

  • WHEN YAML 中 db target 的 expect 包含 status: [200]maxDurationMs: 1000 或其他非 db expect 字段
  • THEN 系统 SHALL 以配置错误退出,提示 expect 包含未知字段

Scenario: db expect rows 中 regex 正则非法

  • WHEN YAML 中 db target 配置 expect.rows: [{ name: { regex: "[invalid" } }]
  • THEN 系统 SHALL 在启动期配置校验失败,而不是延迟到运行期抛错