feat: 结构化 observation 替代 statusDetail,API 层动态构造 detail
- CheckResult: statusDetail -> observation (持久化) + detail (API 动态派生) - 存储: status_detail 列 -> observation TEXT (JSON) - CheckerDefinition: 新增 buildDetail(observation) 方法 - 各 checker 返回结构化 observation,API 层通过 registry 调用 buildDetail - HTTP: bodyPreview 在 status/header 失败时也提前采集 - UDP: observation 包含 durationMs,未响应归为 error failure - CMD: 超时/输出超限时保留已收集 observation - TCP: connectTimeMs 仅含连接建立耗时,不含 banner 等待 - 新增 buildDetail 单测和 mapCheckResult 覆盖测试 - 同步 openspec 主规范,归档 checker-observation 变更
This commit is contained in:
@@ -90,7 +90,7 @@ describe("ProbeEngine", () => {
|
||||
const results = (mockStore as unknown as { _results: Array<Record<string, unknown>> })._results;
|
||||
expect(results.length).toBe(1);
|
||||
expect(results[0]!["matched"]).toBe(true);
|
||||
expect(results[0]!["statusDetail"]).toBe("exitCode=0");
|
||||
expect((results[0]!["observation"] as Record<string, unknown>)["exitCode"]).toBe(0);
|
||||
});
|
||||
|
||||
test("多个目标并发执行", async () => {
|
||||
@@ -181,7 +181,7 @@ describe("ProbeEngine", () => {
|
||||
expect(results[0]!["targetId"]).toBe("reject-cmd");
|
||||
expect(results[0]!["matched"]).toBe(false);
|
||||
expect(results[0]!["durationMs"]).toBeNull();
|
||||
expect(results[0]!["statusDetail"]).toBeNull();
|
||||
expect(results[0]!["observation"]).toBeNull();
|
||||
expect(results[0]!["failure"]).toEqual({
|
||||
kind: "error",
|
||||
message: "boom",
|
||||
@@ -288,7 +288,7 @@ describe("ProbeEngine", () => {
|
||||
const results = (mockStore as unknown as { _results: Array<Record<string, unknown>> })._results;
|
||||
expect(results.length).toBe(1);
|
||||
expect(results[0]!["matched"]).toBe(true);
|
||||
expect(results[0]!["statusDetail"]).toBe("HTTP 200");
|
||||
expect((results[0]!["observation"] as Record<string, unknown>)["statusCode"]).toBe(200);
|
||||
} finally {
|
||||
void httpServer.stop();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user