1
0

refactor: 规范审查与重组,合并细粒度规范,清理过时内容

- 合并 20+ 细粒度 spec 为粗粒度主题规范:dashboard、data-store、probe-engine、probe-api、probe-config 等
- 删除完全冗余规范:data-retention(被 probe-engine+data-store 覆盖)、backend-code-quality(DEVELOPMENT.md 已记录)
- 补充 http-checker 规范至完整标准(配置+执行+expect+校验+observation),匹配代码 440 行实现
- 清理 tcp/udp/llm checker 规范中已废弃 defaults 配置段的残留 Scenario
- 清理 checker-cohesion-structure 中的实现路径引用(src/server/...)
- 统一所有 spec 格式(## Purpose 开头,去除 # Capability/Title 形式)
- 更新 prompt-spec-review.md 审查提示文档
This commit is contained in:
2026-05-22 18:55:18 +08:00
parent cf847ccd7a
commit cfca03b4d6
40 changed files with 1368 additions and 2134 deletions

View File

@@ -25,8 +25,172 @@
#### Scenario: HTTP target 覆盖 headers
- **WHEN** YAML 中某个 HTTP target 显式配置 `http.headers`
- **THEN** 该 target SHALL 使用自身 headers 字段的值,不再与规则文件级 defaults 合并
- **THEN** 该 target SHALL 使用自身 headers 字段的值
#### 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: HTTP 序列化展示摘要
- **WHEN** 系统同步 HTTP target 到 targets 表
- **THEN** `target` 展示摘要 SHALL 为 HTTP URL`config` JSON SHALL 包含 resolved 后的 url、method、headers、body、ignoreSSL、maxBodyBytes 和 maxRedirects
### Requirement: HTTP checker 执行
系统 SHALL 按 HTTP target 配置发起 HTTP 请求,使用引擎注入的 `ctx.signal` 响应超时。系统 SHALL 支持手动重定向跟随(`redirect: "manual"`),在 `maxRedirects` 限制内跟随 301/302/303/307/308 重定向。系统 SHALL 记录完整执行耗时和 HTTP observation并在网络错误、超时、响应体超限或字符编码不支持时产生结构化失败信息。
#### Scenario: HTTP 请求成功
- **WHEN** HTTP target 指向可正常响应的 HTTP 服务,且未配置 expect 或 `expect.status``[200]`
- **THEN** 系统 SHALL 记录 `matched=true``durationMs` 和包含 statusCode、headers、bodyPreview、contentType、contentLength 的 observation
#### Scenario: 使用 ctx.signal 响应超时
- **WHEN** 引擎注入的 `ctx.signal` 在 HTTP 请求过程中 abort
- **THEN** 系统 SHALL 记录 `matched=false`observation SHALL 为 nullfailure 的 kind 为 `error`phase 为 `request`message 包含超时信息
#### Scenario: 网络错误
- **WHEN** HTTP 请求因网络错误DNS 解析失败、连接被拒绝等)失败
- **THEN** 系统 SHALL 记录 `matched=false`observation SHALL 为 nullfailure 的 kind 为 `error`phase 为 `request`
#### Scenario: 重定向跟随
- **WHEN** HTTP target 配置 `http.maxRedirects: 3` 且服务端返回 301/302/303/307/308 重定向
- **THEN** 系统 SHALL 在 maxRedirects 限制内自动跟随重定向,并返回最终响应供 expect 校验
#### Scenario: 重定向次数耗尽
- **WHEN** HTTP target 配置 `http.maxRedirects: 1` 且服务端返回超过 1 次重定向
- **THEN** 系统 SHALL 将最后一次重定向响应作为最终结果返回,不继续跟随
#### Scenario: POST 重定向为 GET
- **WHEN** HTTP target 使用 POST 方法且收到 301 或 302 重定向,或收到 303 重定向
- **THEN** 系统 SHALL 将后续请求方法改为 GET移除 Content-Type 和 Content-Length 请求头,并移除 body
#### Scenario: 跨域重定向移除敏感头
- **WHEN** 重定向到不同 origin 的目标
- **THEN** 系统 SHALL 移除 Authorization 和 Cookie 请求头
#### Scenario: 响应体读取与大小限制
- **WHEN** HTTP target 配置了 body expect 且响应体未超过 `maxBodyBytes`
- **THEN** 系统 SHALL 读取完整响应体,按 Content-Type 字符编码解码,并用于 body expect 校验
#### Scenario: 响应体超过大小限制
- **WHEN** HTTP target 配置了 body expect 且响应体超过 `maxBodyBytes`
- **THEN** 系统 SHALL 停止读取,记录 `matched=false`failure 的 kind 为 `error`phase 为 `body`message 包含响应体超过大小限制的信息
#### Scenario: 不支持的字符编码
- **WHEN** HTTP 响应的 Content-Type 指定了不支持的 charset
- **THEN** 系统 SHALL 记录 `matched=false`failure 的 kind 为 `error`phase 为 `body`message 包含不支持的字符编码信息
#### Scenario: 无 body expect 时不读取响应体
- **WHEN** HTTP target 未配置 `expect.body` 或 body expect 为空数组
- **THEN** 系统 SHALL NOT 读取响应体内容bodyPreview SHALL 为 null
#### Scenario: GET/HEAD 请求不发送 body
- **WHEN** HTTP target 配置 `http.method: GET``http.method: HEAD`
- **THEN** 系统 SHALL NOT 发送请求体,即使配置了 `http.body`
### Requirement: HTTP expect 校验
系统 SHALL 支持 HTTP 专属 expect包括 `status``headers``body``durationMs`,并按 status、headers、early-timeout仅当配置了 body expect 时、body、durationMs 的阶段顺序快速失败。`status` SHALL 保持状态码数组语义支持精确数字100-599和范围模式`1xx``5xx`),未配置时在 Resolved expect 中默认 `[200]``headers` SHALL 使用共享 `RawKeyedExpectations` 输入并在运行期使用 `KeyedExpectations`header key 大小写不敏感。`body` MUST 使用共享 `RawContentExpectations` 数组输入并在运行期使用 `ContentExpectations`,支持直接 ValueMatcher 以及 json/css/xpath 提取器。`durationMs` SHALL 使用共享 `RawValueExpectation` 输入并在运行期使用 `ValueExpectation` 校验完整执行耗时。
#### Scenario: 默认 status 成功语义
- **WHEN** HTTP target 未显式配置 `expect.status`
- **THEN** 系统 SHALL 在 Resolved HTTP expect 中使用默认 `status: [200]` 进行校验
#### Scenario: status 精确值匹配
- **WHEN** HTTP target 配置 `expect.status: [200, 201]` 且响应状态码为 201
- **THEN** 系统 SHALL 判定 status 阶段通过,继续后续 expect 阶段
#### Scenario: status 范围模式匹配
- **WHEN** HTTP target 配置 `expect.status: ["2xx"]` 且响应状态码为 204
- **THEN** 系统 SHALL 判定 status 阶段通过
#### Scenario: status 不匹配快速失败
- **WHEN** HTTP target 配置 `expect.status: [200]` 且响应状态码为 500
- **THEN** 系统 SHALL 立即返回 `matched=false`failure 的 phase 为 `status`
#### Scenario: headers 校验通过
- **WHEN** HTTP target 配置 `expect.headers: {Content-Type: {contains: "application/json"}}` 且响应包含对应 header
- **THEN** 系统 SHALL 判定 headers 阶段通过header key 匹配大小写不敏感
#### Scenario: headers 校验失败
- **WHEN** HTTP target 配置 `expect.headers: {X-Custom: {exists: true}}` 且响应不包含该 header
- **THEN** 系统 SHALL 返回 `matched=false`failure 的 phase 为 `headers`
#### Scenario: body ContentExpectations 校验通过
- **WHEN** HTTP target 配置 `expect.body: [{contains: "ok"}, {json: {path: "$.status", equals: "success"}}]` 且响应体满足全部条件
- **THEN** 系统 SHALL 判定 body 阶段通过
#### Scenario: body ContentExpectations 快速失败
- **WHEN** HTTP target 配置两条 body expectation 且第一条失败
- **THEN** 系统 SHALL 返回第一条失败 expectation 的 failurephase 为 `body`,并 MUST NOT 执行第二条 expectation
#### Scenario: body 非 JSON 响应触发 JSONPath 失败
- **WHEN** HTTP target 配置 json body expectation 但响应体不是合法 JSON
- **THEN** 系统 SHALL 记录 `matched=false`failure 的 kind 为 `error`phase 为 `body`
#### Scenario: early-timeout 快速失败
- **WHEN** HTTP target 配置了 body expect 和 `expect.durationMs: {lte: 500}`,且请求状态码和 headers 通过后已耗时超过 500ms
- **THEN** 系统 SHALL 在读取响应体之前判定 durationMs 超限,不读取响应体,直接返回 `matched=false`failure 的 phase 为 `duration`
#### Scenario: durationMs 校验
- **WHEN** HTTP target 配置 `expect.durationMs: {lte: 1000}` 且完整执行耗时超过 1000ms
- **THEN** 系统 SHALL 返回 `matched=false`failure 的 phase 为 `duration`
### Requirement: HTTP checker 启动期配置校验
系统 SHALL 在启动期对 HTTP checker 的配置契约和语义执行严格校验。HTTP target 的 `http` 分组 SHALL 只允许 `url``method``headers``body``ignoreSSL``maxBodyBytes``maxRedirects` 字段。HTTP expect SHALL 只允许 `status``headers``body``durationMs` 字段。未知字段、非法类型、非法 URL 协议、非法 status 值、非法 maxBodyBytes、非法 ContentExpectations 和不可编译正则 MUST 导致启动期配置错误。语义校验 MUST NOT 修改 Raw HTTP expect 输入。
#### Scenario: http.url 为空字符串
- **WHEN** YAML 中 HTTP target 配置 `http.url: ""`
- **THEN** 系统 SHALL 以配置错误退出,提示缺少 http.url 字段
#### Scenario: http.url 协议非法
- **WHEN** YAML 中 HTTP target 的 `http.url` 不以 `http://``https://` 开头
- **THEN** 系统 SHALL 以配置错误退出,提示 URL 格式不合法
#### Scenario: http.url 格式非法
- **WHEN** YAML 中 HTTP target 的 `http.url` 不是合法 URL
- **THEN** 系统 SHALL 以配置错误退出,提示 URL 格式不合法
#### Scenario: http.maxBodyBytes 格式非法
- **WHEN** YAML 中 HTTP target 的 `http.maxBodyBytes` 不是合法 size 值
- **THEN** 系统 SHALL 以配置错误退出,提示 maxBodyBytes 格式错误
#### Scenario: http 分组未知字段失败
- **WHEN** YAML 中 HTTP target 的 `http` 分组包含未知字段
- **THEN** 系统 SHALL 以配置错误退出,提示 http 分组包含未知字段
#### Scenario: expect.status 数字非法
- **WHEN** YAML 中 HTTP target 的 `expect.status` 包含非整数或不在 100-599 范围内的数字
- **THEN** 系统 SHALL 以配置错误退出,提示 status 数字不合法
#### Scenario: expect.status 模式非法
- **WHEN** YAML 中 HTTP target 的 `expect.status` 包含不符合 `1xx``5xx` 格式的字符串
- **THEN** 系统 SHALL 以配置错误退出,提示 status 模式不合法
#### Scenario: expect.body 必须为数组
- **WHEN** YAML 中 HTTP target 的 `expect.body` 已配置但不是数组
- **THEN** 系统 SHALL 以配置错误退出,提示 expect.body 必须为数组
#### Scenario: HTTP expect 未知字段失败
- **WHEN** YAML 中 HTTP target 的 expect 包含 `connected``exitCode``maxDurationMs` 或其他非 HTTP expect 字段
- **THEN** 系统 SHALL 以配置错误退出,提示 expect 包含未知字段
### Requirement: HTTP observation 与 detail
HTTP checker SHALL 在 observation 中记录 statusCodenumber、headersRecord<string, string>,截断至前 20 个、bodyPreviewstring | null截断至前 1024 字符、contentTypestring | null、contentLengthnumber | null。API detail SHALL 由 `buildDetail` 从 observation 动态构造,格式为 `HTTP {statusCode}`。网络错误或超时导致无法收集 observation 时observation SHALL 为 nulldetail SHALL 为 null。
#### Scenario: 正常响应 observation
- **WHEN** HTTP 请求成功返回
- **THEN** observation SHALL 包含 statusCode、截断后的 headers、截断后的 bodyPreview、contentType 和 contentLength
#### Scenario: 未读取响应体时 bodyPreview 为 null
- **WHEN** HTTP target 未配置 body expect
- **THEN** observation.bodyPreview SHALL 为 null
#### Scenario: 请求失败 observation 为 null
- **WHEN** HTTP 请求因网络错误或超时失败
- **THEN** observation SHALL 为 nulldetail SHALL 为 null
#### Scenario: detail 格式
- **WHEN** API 序列化 HTTP CheckResult
- **THEN** detail SHALL 为 `HTTP {statusCode}` 格式(如 `HTTP 200`